LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sc/source/core/data - column.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 872 1448 60.2 %
Date: 2013-07-09 Functions: 137 179 76.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "column.hxx"
      21             : #include "scitems.hxx"
      22             : #include "formulacell.hxx"
      23             : #include "document.hxx"
      24             : #include "docpool.hxx"
      25             : #include "attarray.hxx"
      26             : #include "patattr.hxx"
      27             : #include "compiler.hxx"
      28             : #include "brdcst.hxx"
      29             : #include "markdata.hxx"
      30             : #include "detfunc.hxx"          // for Notes in Sort/Swap
      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             : 
      43             : #include <svl/poolcach.hxx>
      44             : #include <svl/zforlist.hxx>
      45             : #include <editeng/scripttypeitem.hxx>
      46             : #include "editeng/fieldupdater.hxx"
      47             : 
      48             : #include <cstring>
      49             : #include <map>
      50             : #include <cstdio>
      51             : #include <boost/scoped_ptr.hpp>
      52             : 
      53             : using ::editeng::SvxBorderLine;
      54             : using namespace formula;
      55             : 
      56             : namespace {
      57             : 
      58       29699 : inline bool IsAmbiguousScriptNonZero( sal_uInt8 nScript )
      59             : {
      60             :     //! move to a header file
      61          99 :     return ( nScript != SCRIPTTYPE_LATIN &&
      62          99 :              nScript != SCRIPTTYPE_ASIAN &&
      63       29798 :              nScript != SCRIPTTYPE_COMPLEX &&
      64       29699 :              nScript != 0 );
      65             : }
      66             : 
      67             : }
      68             : 
      69      129310 : ScNeededSizeOptions::ScNeededSizeOptions() :
      70      129310 :     pPattern(NULL), bFormula(false), bSkipMerged(true), bGetFont(true), bTotalSize(false)
      71             : {
      72      129310 : }
      73             : 
      74     1658880 : ScColumn::ScColumn() :
      75             :     maCellTextAttrs(MAXROWCOUNT),
      76             :     maBroadcasters(MAXROWCOUNT),
      77             :     maCells(MAXROWCOUNT),
      78             :     nCol( 0 ),
      79             :     pAttrArray( NULL ),
      80             :     pDocument( NULL ),
      81     1658880 :     mbDirtyGroups(true)
      82             : {
      83     1658880 : }
      84             : 
      85             : 
      86     3108864 : ScColumn::~ScColumn()
      87             : {
      88     1554432 :     FreeAll();
      89     1554432 :     delete pAttrArray;
      90     1554432 : }
      91             : 
      92             : 
      93     1658880 : void ScColumn::Init(SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc)
      94             : {
      95     1658880 :     nCol = nNewCol;
      96     1658880 :     nTab = nNewTab;
      97     1658880 :     pDocument = pDoc;
      98     1658880 :     pAttrArray = new ScAttrArray( nCol, nTab, pDocument );
      99     1658880 : }
     100             : 
     101             : 
     102           0 : SCsROW ScColumn::GetNextUnprotected( SCROW nRow, bool bUp ) const
     103             : {
     104           0 :     return pAttrArray->GetNextUnprotected(nRow, bUp);
     105             : }
     106             : 
     107             : 
     108      239331 : sal_uInt16 ScColumn::GetBlockMatrixEdges( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const
     109             : {
     110             :     using namespace sc;
     111             : 
     112      239331 :     if (!ValidRow(nRow1) || !ValidRow(nRow2) || nRow1 > nRow2)
     113           0 :         return 0;
     114             : 
     115      239331 :     ScAddress aOrigin(ScAddress::INITIALIZE_INVALID);
     116             : 
     117      239331 :     if (nRow1 == nRow2)
     118             :     {
     119      238308 :         std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow1);
     120      238308 :         if (aPos.first->type != sc::element_type_formula)
     121      237992 :             return 0;
     122             : 
     123         316 :         const ScFormulaCell* pCell = sc::formula_block::at(*aPos.first->data, aPos.second);
     124         316 :         if (!pCell->GetMatrixFlag())
     125         316 :             return 0;
     126             : 
     127           0 :         return pCell->GetMatrixEdge(aOrigin);
     128             :     }
     129             : 
     130        1023 :     bool bOpen = false;
     131        1023 :     sal_uInt16 nEdges = 0;
     132             : 
     133        1023 :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow1);
     134        1023 :     sc::CellStoreType::const_iterator it = aPos.first;
     135        1023 :     size_t nOffset = aPos.second;
     136        1023 :     SCROW nRow = nRow1;
     137        2812 :     for (;it != maCells.end() && nRow <= nRow2; ++it, nOffset = 0)
     138             :     {
     139        1789 :         if (it->type != sc::element_type_formula)
     140             :         {
     141             :             // Skip this block.
     142        1761 :             nRow += it->size - nOffset;
     143        1761 :             continue;
     144             :         }
     145             : 
     146          28 :         size_t nRowsToRead = nRow2 - nRow + 1;
     147          28 :         size_t nEnd = std::min(it->size, nRowsToRead);
     148          28 :         sc::formula_block::const_iterator itCell = sc::formula_block::begin(*it->data);
     149          28 :         std::advance(itCell, nOffset);
     150          86 :         for (size_t i = nOffset; i < nEnd; ++itCell, ++i)
     151             :         {
     152             :             // Loop inside the formula block.
     153          58 :             const ScFormulaCell* pCell = *itCell;
     154          58 :             if (!pCell->GetMatrixFlag())
     155          58 :                 continue;
     156             : 
     157           0 :             nEdges = pCell->GetMatrixEdge(aOrigin);
     158           0 :             if (!nEdges)
     159           0 :                 continue;
     160             : 
     161           0 :             if (nEdges & MatrixEdgeTop)
     162           0 :                 bOpen = true;       // top edge opens, keep on looking
     163           0 :             else if (!bOpen)
     164           0 :                 return nEdges | MatrixEdgeOpen; // there's something that wasn't opened
     165           0 :             else if (nEdges & MatrixEdgeInside)
     166           0 :                 return nEdges;      // inside
     167             :             // (nMask & 16 and  (4 and not 16)) or
     168             :             // (nMask & 4  and (16 and not 4))
     169           0 :             if (((nMask & MatrixEdgeRight) && (nEdges & MatrixEdgeLeft)  && !(nEdges & MatrixEdgeRight)) ||
     170           0 :                 ((nMask & MatrixEdgeLeft)  && (nEdges & MatrixEdgeRight) && !(nEdges & MatrixEdgeLeft)))
     171           0 :                 return nEdges;      // only left/right edge
     172             : 
     173           0 :             if (nEdges & MatrixEdgeBottom)
     174           0 :                 bOpen = false;      // bottom edge closes
     175             :         }
     176             : 
     177          28 :         nRow += nEnd;
     178             :     }
     179        1023 :     if (bOpen)
     180           0 :         nEdges |= MatrixEdgeOpen; // not closed, matrix continues
     181             : 
     182        1023 :     return nEdges;
     183             : }
     184             : 
     185             : 
     186       68608 : bool ScColumn::HasSelectionMatrixFragment(const ScMarkData& rMark) const
     187             : {
     188             :     using namespace sc;
     189             : 
     190       68608 :     if (!rMark.IsMultiMarked())
     191           0 :         return false;
     192             : 
     193       68608 :     ScAddress aOrigin(ScAddress::INITIALIZE_INVALID);
     194       68608 :     ScAddress aCurOrigin = aOrigin;
     195             : 
     196       68608 :     bool bOpen = false;
     197       68608 :     ScRangeList aRanges = rMark.GetMarkedRanges();
     198      292864 :     for (size_t i = 0, n = aRanges.size(); i < n; ++i)
     199             :     {
     200      224256 :         const ScRange& r = *aRanges[i];
     201      224256 :         if (nTab < r.aStart.Tab() || r.aEnd.Tab() < nTab)
     202      223787 :             continue;
     203             : 
     204      224256 :         if (nCol < r.aStart.Col() || r.aEnd.Col() < nCol)
     205      223787 :             continue;
     206             : 
     207         469 :         SCROW nTop = r.aStart.Row(), nBottom = r.aEnd.Row();
     208         469 :         SCROW nRow = nTop;
     209         469 :         std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
     210         469 :         sc::CellStoreType::const_iterator it = aPos.first;
     211         469 :         size_t nOffset = aPos.second;
     212             : 
     213         973 :         for (;it != maCells.end() && nRow <= nBottom; ++it, nOffset = 0)
     214             :         {
     215         504 :             if (it->type != sc::element_type_formula)
     216             :             {
     217             :                 // Skip this block.
     218         504 :                 nRow += it->size - nOffset;
     219         504 :                 continue;
     220             :             }
     221             : 
     222             :             // This is a formula cell block.
     223           0 :             size_t nRowsToRead = nBottom - nRow + 1;
     224           0 :             size_t nEnd = std::min(it->size, nRowsToRead);
     225           0 :             sc::formula_block::const_iterator itCell = sc::formula_block::begin(*it->data);
     226           0 :             std::advance(itCell, nOffset);
     227           0 :             for (size_t j = nOffset; j < nEnd; ++itCell, ++j)
     228             :             {
     229             :                 // Loop inside the formula block.
     230           0 :                 const ScFormulaCell* pCell = *itCell;
     231           0 :                 if (!pCell->GetMatrixFlag())
     232             :                     // cell is not a part of a matrix.
     233           0 :                     continue;
     234             : 
     235           0 :                 sal_uInt16 nEdges = pCell->GetMatrixEdge(aOrigin);
     236           0 :                 if (!nEdges)
     237           0 :                     continue;
     238             : 
     239           0 :                 bool bFound = false;
     240             : 
     241           0 :                 if (nEdges & MatrixEdgeTop)
     242           0 :                     bOpen = true;   // top edge opens, keep on looking
     243           0 :                 else if (!bOpen)
     244           0 :                     return true;    // there's something that wasn't opened
     245           0 :                 else if (nEdges & MatrixEdgeInside)
     246           0 :                     bFound = true;  // inside, all selected?
     247             : 
     248           0 :                 if ((((nEdges & MatrixEdgeLeft) | MatrixEdgeRight) ^ ((nEdges & MatrixEdgeRight) | MatrixEdgeLeft)))
     249             :                     // either left or right, but not both.
     250           0 :                     bFound = true;  // only left/right edge, all selected?
     251             : 
     252           0 :                 if (nEdges & MatrixEdgeBottom)
     253           0 :                     bOpen = false;  // bottom edge closes
     254             : 
     255           0 :                 if (bFound)
     256             :                 {
     257             :                     // Check if the matrix is inside the selection in its entirety.
     258             :                     //
     259             :                     // TODO: It's more efficient to skip the matrix range if
     260             :                     // it's within selection, to avoid checking it again and
     261             :                     // again.
     262             : 
     263           0 :                     if (aCurOrigin != aOrigin)
     264             :                     {   // new matrix to check?
     265           0 :                         aCurOrigin = aOrigin;
     266             :                         const ScFormulaCell* pFCell;
     267           0 :                         if (pCell->GetMatrixFlag() == MM_REFERENCE)
     268           0 :                             pFCell = pDocument->GetFormulaCell(aOrigin);
     269             :                         else
     270           0 :                             pFCell = pCell;
     271             : 
     272             :                         SCCOL nC;
     273             :                         SCROW nR;
     274           0 :                         pFCell->GetMatColsRows(nC, nR);
     275           0 :                         ScRange aRange(aOrigin, ScAddress(aOrigin.Col()+nC-1, aOrigin.Row()+nR-1, aOrigin.Tab()));
     276           0 :                         if (rMark.IsAllMarked(aRange))
     277           0 :                             bFound = false;
     278             :                     }
     279             :                     else
     280           0 :                         bFound = false;     // done already
     281             :                 }
     282             : 
     283           0 :                 if (bFound)
     284           0 :                     return true;
     285             :             }
     286             : 
     287           0 :             nRow += nEnd;
     288             :         }
     289             :     }
     290             : 
     291       68608 :     if (bOpen)
     292           0 :         return true;
     293             : 
     294       68608 :     return false;
     295             : }
     296             : 
     297             : 
     298    11554225 : bool ScColumn::HasAttrib( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const
     299             : {
     300    11554225 :     return pAttrArray->HasAttrib( nRow1, nRow2, nMask );
     301             : }
     302             : 
     303             : 
     304           0 : bool ScColumn::HasAttribSelection( const ScMarkData& rMark, sal_uInt16 nMask ) const
     305             : {
     306           0 :     bool bFound = false;
     307             : 
     308             :     SCROW nTop;
     309             :     SCROW nBottom;
     310             : 
     311           0 :     if (rMark.IsMultiMarked())
     312             :     {
     313           0 :         ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol );
     314           0 :         while (aMarkIter.Next( nTop, nBottom ) && !bFound)
     315             :         {
     316           0 :             if (pAttrArray->HasAttrib( nTop, nBottom, nMask ))
     317           0 :                 bFound = true;
     318           0 :         }
     319             :     }
     320             : 
     321           0 :     return bFound;
     322             : }
     323             : 
     324             : 
     325        5977 : bool ScColumn::ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
     326             :                             SCCOL& rPaintCol, SCROW& rPaintRow,
     327             :                             bool bRefresh )
     328             : {
     329        5977 :     return pAttrArray->ExtendMerge( nThisCol, nStartRow, nEndRow, rPaintCol, rPaintRow, bRefresh );
     330             : }
     331             : 
     332             : 
     333      128000 : void ScColumn::MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, bool bDeep ) const
     334             : {
     335             :     SCROW nTop;
     336             :     SCROW nBottom;
     337             : 
     338      128000 :     if ( rMark.IsMultiMarked() )
     339             :     {
     340      128000 :         const ScMarkArray* pArray = rMark.GetArray() + nCol;
     341      128000 :         if ( pArray->HasMarks() )
     342             :         {
     343        6900 :             ScMarkArrayIter aMarkIter( pArray );
     344       20781 :             while (aMarkIter.Next( nTop, nBottom ))
     345       13881 :                 pAttrArray->MergePatternArea( nTop, nBottom, rState, bDeep );
     346             :         }
     347             :     }
     348      128000 : }
     349             : 
     350             : 
     351       55839 : void ScColumn::MergePatternArea( ScMergePatternState& rState, SCROW nRow1, SCROW nRow2, bool bDeep ) const
     352             : {
     353       55839 :     pAttrArray->MergePatternArea( nRow1, nRow2, rState, bDeep );
     354       55839 : }
     355             : 
     356             : 
     357         176 : void ScColumn::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner,
     358             :                             ScLineFlags& rFlags,
     359             :                             SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight ) const
     360             : {
     361         176 :     pAttrArray->MergeBlockFrame( pLineOuter, pLineInner, rFlags, nStartRow, nEndRow, bLeft, nDistRight );
     362         176 : }
     363             : 
     364             : 
     365        1721 : void ScColumn::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner,
     366             :                             SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight )
     367             : {
     368        1721 :     pAttrArray->ApplyBlockFrame( pLineOuter, pLineInner, nStartRow, nEndRow, bLeft, nDistRight );
     369        1721 : }
     370             : 
     371             : 
     372       41682 : const ScPatternAttr* ScColumn::GetPattern( SCROW nRow ) const
     373             : {
     374       41682 :     return pAttrArray->GetPattern( nRow );
     375             : }
     376             : 
     377             : 
     378       10756 : const SfxPoolItem* ScColumn::GetAttr( SCROW nRow, sal_uInt16 nWhich ) const
     379             : {
     380       10756 :     return &pAttrArray->GetPattern( nRow )->GetItemSet().Get(nWhich);
     381             : }
     382             : 
     383             : 
     384       10496 : const ScPatternAttr* ScColumn::GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow ) const
     385             : {
     386       10496 :     ::std::map< const ScPatternAttr*, size_t > aAttrMap;
     387       10496 :     const ScPatternAttr* pMaxPattern = 0;
     388       10496 :     size_t nMaxCount = 0;
     389             : 
     390       10496 :     ScAttrIterator aAttrIter( pAttrArray, nStartRow, nEndRow );
     391             :     const ScPatternAttr* pPattern;
     392       10496 :     SCROW nAttrRow1 = 0, nAttrRow2 = 0;
     393             : 
     394       31518 :     while( (pPattern = aAttrIter.Next( nAttrRow1, nAttrRow2 )) != 0 )
     395             :     {
     396       10526 :         size_t& rnCount = aAttrMap[ pPattern ];
     397       10526 :         rnCount += (nAttrRow2 - nAttrRow1 + 1);
     398       10526 :         if( rnCount > nMaxCount )
     399             :         {
     400       10526 :             pMaxPattern = pPattern;
     401       10526 :             nMaxCount = rnCount;
     402             :         }
     403             :     }
     404             : 
     405       10496 :     return pMaxPattern;
     406             : }
     407             : 
     408          10 : sal_uInt32 ScColumn::GetNumberFormat( SCROW nStartRow, SCROW nEndRow ) const
     409             : {
     410             :     SCROW nPatStartRow, nPatEndRow;
     411          10 :     const ScPatternAttr* pPattern = pAttrArray->GetPatternRange(nPatStartRow, nPatEndRow, nStartRow);
     412          10 :     sal_uInt32 nFormat = pPattern->GetNumberFormat(pDocument->GetFormatTable());
     413          30 :     while (nEndRow > nPatEndRow)
     414             :     {
     415          10 :         nStartRow = nPatEndRow + 1;
     416          10 :         pPattern = pAttrArray->GetPatternRange(nPatStartRow, nPatEndRow, nStartRow);
     417          10 :         sal_uInt32 nTmpFormat = pPattern->GetNumberFormat(pDocument->GetFormatTable());
     418          10 :         if (nFormat != nTmpFormat)
     419           0 :             return 0;
     420             :     }
     421          10 :     return nFormat;
     422             : }
     423             : 
     424             : 
     425       51812 : sal_uInt32 ScColumn::GetNumberFormat( SCROW nRow ) const
     426             : {
     427       51812 :     return pAttrArray->GetPattern( nRow )->GetNumberFormat( pDocument->GetFormatTable() );
     428             : }
     429             : 
     430             : 
     431       68608 : SCsROW ScColumn::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark, ScEditDataArray* pDataArray )
     432             : {
     433       68608 :     SCROW nTop = 0;
     434       68608 :     SCROW nBottom = 0;
     435       68608 :     bool bFound = false;
     436             : 
     437       68608 :     if ( rMark.IsMultiMarked() )
     438             :     {
     439       68608 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     440      137695 :         while (aMarkIter.Next( nTop, nBottom ))
     441             :         {
     442         479 :             pAttrArray->ApplyCacheArea( nTop, nBottom, pCache, pDataArray );
     443         479 :             bFound = true;
     444       68608 :         }
     445             :     }
     446             : 
     447       68608 :     if (!bFound)
     448       68145 :         return -1;
     449         463 :     else if (nTop==0 && nBottom==MAXROW)
     450           0 :         return 0;
     451             :     else
     452         463 :         return nBottom;
     453             : }
     454             : 
     455             : 
     456        6144 : void ScColumn::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
     457             : {
     458             :     SCROW nTop;
     459             :     SCROW nBottom;
     460             : 
     461        6144 :     if ( pAttrArray && rMark.IsMultiMarked() )
     462             :     {
     463        6144 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     464       12314 :         while (aMarkIter.Next( nTop, nBottom ))
     465        6170 :             pAttrArray->ChangeIndent(nTop, nBottom, bIncrement);
     466             :     }
     467        6144 : }
     468             : 
     469           0 : void ScColumn::ClearSelectionItems( const sal_uInt16* pWhich,const ScMarkData& rMark )
     470             : {
     471             :     SCROW nTop;
     472             :     SCROW nBottom;
     473             : 
     474           0 :     if ( pAttrArray && rMark.IsMultiMarked() )
     475             :     {
     476           0 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     477           0 :         while (aMarkIter.Next( nTop, nBottom ))
     478           0 :             pAttrArray->ClearItems(nTop, nBottom, pWhich);
     479             :     }
     480           0 : }
     481             : 
     482             : 
     483       79872 : void ScColumn::DeleteSelection( sal_uInt16 nDelFlag, const ScMarkData& rMark )
     484             : {
     485             :     SCROW nTop;
     486             :     SCROW nBottom;
     487             : 
     488       79872 :     if ( rMark.IsMultiMarked() )
     489             :     {
     490       79872 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     491      159906 :         while (aMarkIter.Next( nTop, nBottom ))
     492       80034 :             DeleteArea(nTop, nBottom, nDelFlag);
     493             :     }
     494       79872 : }
     495             : 
     496             : 
     497         188 : void ScColumn::ApplyPattern( SCROW nRow, const ScPatternAttr& rPatAttr )
     498             : {
     499         188 :     const SfxItemSet* pSet = &rPatAttr.GetItemSet();
     500         188 :     SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
     501             : 
     502         188 :     const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
     503             : 
     504             :     //  true = keep old content
     505             : 
     506         188 :     ScPatternAttr* pNewPattern = (ScPatternAttr*) &aCache.ApplyTo( *pPattern, true );
     507         188 :     ScDocumentPool::CheckRef( *pPattern );
     508         188 :     ScDocumentPool::CheckRef( *pNewPattern );
     509             : 
     510         188 :     if (pNewPattern != pPattern)
     511         188 :       pAttrArray->SetPattern( nRow, pNewPattern );
     512         188 : }
     513             : 
     514             : 
     515       29833 : void ScColumn::ApplyPatternArea( SCROW nStartRow, SCROW nEndRow, const ScPatternAttr& rPatAttr,
     516             :                                  ScEditDataArray* pDataArray )
     517             : {
     518       29833 :     const SfxItemSet* pSet = &rPatAttr.GetItemSet();
     519       29833 :     SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
     520       29833 :     pAttrArray->ApplyCacheArea( nStartRow, nEndRow, &aCache, pDataArray );
     521       29833 : }
     522             : 
     523       25281 : bool ScColumn::SetAttrEntries(ScAttrEntry* pData, SCSIZE nSize)
     524             : {
     525       25281 :     return pAttrArray->SetAttrEntries(pData, nSize);
     526             : }
     527             : 
     528           0 : void ScColumn::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
     529             :         const ScPatternAttr& rPattern, short nNewType )
     530             : {
     531           0 :     const SfxItemSet* pSet = &rPattern.GetItemSet();
     532           0 :     SfxItemPoolCache aCache( pDocument->GetPool(), pSet );
     533           0 :     SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
     534           0 :     SCROW nEndRow = rRange.aEnd.Row();
     535           0 :     for ( SCROW nRow = rRange.aStart.Row(); nRow <= nEndRow; nRow++ )
     536             :     {
     537             :         SCROW nRow1, nRow2;
     538             :         const ScPatternAttr* pPattern = pAttrArray->GetPatternRange(
     539           0 :             nRow1, nRow2, nRow );
     540           0 :         sal_uInt32 nFormat = pPattern->GetNumberFormat( pFormatter );
     541           0 :         short nOldType = pFormatter->GetType( nFormat );
     542           0 :         if ( nOldType == nNewType || pFormatter->IsCompatible( nOldType, nNewType ) )
     543           0 :             nRow = nRow2;
     544             :         else
     545             :         {
     546           0 :             SCROW nNewRow1 = std::max( nRow1, nRow );
     547           0 :             SCROW nNewRow2 = std::min( nRow2, nEndRow );
     548           0 :             pAttrArray->ApplyCacheArea( nNewRow1, nNewRow2, &aCache );
     549           0 :             nRow = nNewRow2;
     550             :         }
     551           0 :     }
     552           0 : }
     553             : 
     554        4360 : void ScColumn::AddCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex )
     555             : {
     556        4360 :     pAttrArray->AddCondFormat( nStartRow, nEndRow, nIndex );
     557        4360 : }
     558             : 
     559           0 : void ScColumn::RemoveCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex )
     560             : {
     561           0 :     pAttrArray->RemoveCondFormat( nStartRow, nEndRow, nIndex );
     562           0 : }
     563             : 
     564             : 
     565           3 : void ScColumn::ApplyStyle( SCROW nRow, const ScStyleSheet& rStyle )
     566             : {
     567           3 :     const ScPatternAttr* pPattern = pAttrArray->GetPattern(nRow);
     568           3 :     ScPatternAttr* pNewPattern = new ScPatternAttr(*pPattern);
     569           3 :     if (pNewPattern)
     570             :     {
     571           3 :         pNewPattern->SetStyleSheet((ScStyleSheet*)&rStyle);
     572           3 :         pAttrArray->SetPattern(nRow, pNewPattern, true);
     573           3 :         delete pNewPattern;
     574             :     }
     575           3 : }
     576             : 
     577             : 
     578       78865 : void ScColumn::ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, const ScStyleSheet& rStyle )
     579             : {
     580       78865 :     pAttrArray->ApplyStyleArea(nStartRow, nEndRow, (ScStyleSheet*)&rStyle);
     581       78865 : }
     582             : 
     583             : 
     584      109568 : void ScColumn::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
     585             : {
     586             :     SCROW nTop;
     587             :     SCROW nBottom;
     588             : 
     589      109568 :     if ( rMark.IsMultiMarked() )
     590             :     {
     591      109568 :         ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     592      219875 :         while (aMarkIter.Next( nTop, nBottom ))
     593      110307 :             pAttrArray->ApplyStyleArea(nTop, nBottom, (ScStyleSheet*)&rStyle);
     594             :     }
     595      109568 : }
     596             : 
     597             : 
     598           0 : void ScColumn::ApplySelectionLineStyle( const ScMarkData& rMark,
     599             :                                     const SvxBorderLine* pLine, bool bColorOnly )
     600             : {
     601           0 :     if ( bColorOnly && !pLine )
     602           0 :         return;
     603             : 
     604             :     SCROW nTop;
     605             :     SCROW nBottom;
     606             : 
     607           0 :     if (rMark.IsMultiMarked())
     608             :     {
     609           0 :         ScMarkArrayIter aMarkIter( rMark.GetArray()+nCol );
     610           0 :         while (aMarkIter.Next( nTop, nBottom ))
     611           0 :             pAttrArray->ApplyLineStyleArea(nTop, nBottom, pLine, bColorOnly );
     612             :     }
     613             : }
     614             : 
     615             : 
     616          44 : const ScStyleSheet* ScColumn::GetStyle( SCROW nRow ) const
     617             : {
     618          44 :     return pAttrArray->GetPattern( nRow )->GetStyleSheet();
     619             : }
     620             : 
     621             : 
     622        6224 : const ScStyleSheet* ScColumn::GetSelectionStyle( const ScMarkData& rMark, bool& rFound ) const
     623             : {
     624        6224 :     rFound = false;
     625        6224 :     if (!rMark.IsMultiMarked())
     626             :     {
     627             :         OSL_FAIL("No selection in ScColumn::GetSelectionStyle");
     628           0 :         return NULL;
     629             :     }
     630             : 
     631        6224 :     bool bEqual = true;
     632             : 
     633        6224 :     const ScStyleSheet* pStyle = NULL;
     634             :     const ScStyleSheet* pNewStyle;
     635             : 
     636        6224 :     ScMarkArrayIter aMarkIter( rMark.GetArray() + nCol );
     637             :     SCROW nTop;
     638             :     SCROW nBottom;
     639       18700 :     while (bEqual && aMarkIter.Next( nTop, nBottom ))
     640             :     {
     641        6252 :         ScAttrIterator aAttrIter( pAttrArray, nTop, nBottom );
     642             :         SCROW nRow;
     643             :         SCROW nDummy;
     644             :         const ScPatternAttr* pPattern;
     645       18836 :         while (bEqual && ( pPattern = aAttrIter.Next( nRow, nDummy ) ) != NULL)
     646             :         {
     647        6332 :             pNewStyle = pPattern->GetStyleSheet();
     648        6332 :             rFound = true;
     649        6332 :             if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
     650           0 :                 bEqual = false;                                             // difference
     651        6332 :             pStyle = pNewStyle;
     652             :         }
     653             :     }
     654             : 
     655        6224 :     return bEqual ? pStyle : NULL;
     656             : }
     657             : 
     658             : 
     659       12398 : const ScStyleSheet* ScColumn::GetAreaStyle( bool& rFound, SCROW nRow1, SCROW nRow2 ) const
     660             : {
     661       12398 :     rFound = false;
     662             : 
     663       12398 :     bool bEqual = true;
     664             : 
     665       12398 :     const ScStyleSheet* pStyle = NULL;
     666             :     const ScStyleSheet* pNewStyle;
     667             : 
     668       12398 :     ScAttrIterator aAttrIter( pAttrArray, nRow1, nRow2 );
     669             :     SCROW nRow;
     670             :     SCROW nDummy;
     671             :     const ScPatternAttr* pPattern;
     672       37194 :     while (bEqual && ( pPattern = aAttrIter.Next( nRow, nDummy ) ) != NULL)
     673             :     {
     674       12398 :         pNewStyle = pPattern->GetStyleSheet();
     675       12398 :         rFound = true;
     676       12398 :         if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
     677           0 :             bEqual = false;                                             // difference
     678       12398 :         pStyle = pNewStyle;
     679             :     }
     680             : 
     681       12398 :     return bEqual ? pStyle : NULL;
     682             : }
     683             : 
     684     3075072 : void ScColumn::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset )
     685             : {
     686     3075072 :     pAttrArray->FindStyleSheet( pStyleSheet, rUsedRows, bReset );
     687     3075072 : }
     688             : 
     689           0 : bool ScColumn::IsStyleSheetUsed( const ScStyleSheet& rStyle, bool bGatherAllStyles ) const
     690             : {
     691           0 :     return pAttrArray->IsStyleSheetUsed( rStyle, bGatherAllStyles );
     692             : }
     693             : 
     694             : 
     695        4498 : bool ScColumn::ApplyFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
     696             : {
     697        4498 :     return pAttrArray->ApplyFlags( nStartRow, nEndRow, nFlags );
     698             : }
     699             : 
     700             : 
     701        5761 : bool ScColumn::RemoveFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
     702             : {
     703        5761 :     return pAttrArray->RemoveFlags( nStartRow, nEndRow, nFlags );
     704             : }
     705             : 
     706             : 
     707           5 : void ScColumn::ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt16* pWhich )
     708             : {
     709           5 :     pAttrArray->ClearItems( nStartRow, nEndRow, pWhich );
     710           5 : }
     711             : 
     712             : 
     713         163 : void ScColumn::SetPattern( SCROW nRow, const ScPatternAttr& rPatAttr, bool bPutToPool )
     714             : {
     715         163 :     pAttrArray->SetPattern( nRow, &rPatAttr, bPutToPool );
     716         163 : }
     717             : 
     718             : 
     719          31 : void ScColumn::SetPatternArea( SCROW nStartRow, SCROW nEndRow,
     720             :                                 const ScPatternAttr& rPatAttr, bool bPutToPool )
     721             : {
     722          31 :     pAttrArray->SetPatternArea( nStartRow, nEndRow, &rPatAttr, bPutToPool );
     723          31 : }
     724             : 
     725             : 
     726        2268 : void ScColumn::ApplyAttr( SCROW nRow, const SfxPoolItem& rAttr )
     727             : {
     728             :     //  in order to only create a new SetItem, we don't need SfxItemPoolCache.
     729             :     //! Warning: SfxItemPoolCache seems to create to many Refs for the new SetItem ??
     730             : 
     731        2268 :     ScDocumentPool* pDocPool = pDocument->GetPool();
     732             : 
     733        2268 :     const ScPatternAttr* pOldPattern = pAttrArray->GetPattern( nRow );
     734        2268 :     ScPatternAttr* pTemp = new ScPatternAttr(*pOldPattern);
     735        2268 :     pTemp->GetItemSet().Put(rAttr);
     736        2268 :     const ScPatternAttr* pNewPattern = (const ScPatternAttr*) &pDocPool->Put( *pTemp );
     737             : 
     738        2268 :     if ( pNewPattern != pOldPattern )
     739        2244 :         pAttrArray->SetPattern( nRow, pNewPattern );
     740             :     else
     741          24 :         pDocPool->Remove( *pNewPattern );       // free up resources
     742             : 
     743        2268 :     delete pTemp;
     744        2268 : }
     745             : 
     746         192 : ScDocument& ScColumn::GetDoc()
     747             : {
     748         192 :     return *pDocument;
     749             : }
     750             : 
     751        1131 : const ScDocument& ScColumn::GetDoc() const
     752             : {
     753        1131 :     return *pDocument;
     754             : }
     755             : 
     756       88489 : ScRefCellValue ScColumn::GetCellValue( SCROW nRow ) const
     757             : {
     758       88489 :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
     759       88489 :     if (aPos.first == maCells.end())
     760           0 :         return ScRefCellValue();
     761             : 
     762       88489 :     return GetCellValue(aPos.first, aPos.second);
     763             : }
     764             : 
     765       89817 : ScRefCellValue ScColumn::GetCellValue( const sc::CellStoreType::const_iterator& itPos, size_t nOffset ) const
     766             : {
     767       89817 :     ScRefCellValue aVal; // Defaults to empty cell.
     768       89817 :     switch (itPos->type)
     769             :     {
     770             :         case sc::element_type_numeric:
     771             :             // Numeric cell
     772       41609 :             aVal.mfValue = sc::numeric_block::at(*itPos->data, nOffset);
     773       41609 :             aVal.meType = CELLTYPE_VALUE;
     774       41609 :         break;
     775             :         case sc::element_type_string:
     776             :             // String cell
     777       15503 :             aVal.mpString = &sc::string_block::at(*itPos->data, nOffset);
     778       15503 :             aVal.meType = CELLTYPE_STRING;
     779       15503 :         break;
     780             :         case sc::element_type_edittext:
     781             :             // Edit cell
     782         904 :             aVal.mpEditText = sc::edittext_block::at(*itPos->data, nOffset);
     783         904 :             aVal.meType = CELLTYPE_EDIT;
     784         904 :         break;
     785             :         case sc::element_type_formula:
     786             :             // Formula cell
     787        3735 :             aVal.mpFormula = sc::formula_block::at(*itPos->data, nOffset);
     788        3735 :             aVal.meType = CELLTYPE_FORMULA;
     789        3735 :         break;
     790             :         default:
     791             :             ;
     792             :     }
     793             : 
     794       89817 :     return aVal;
     795             : }
     796             : 
     797             : namespace {
     798             : 
     799           0 : ScFormulaCell* cloneFormulaCell(ScDocument* pDoc, const ScAddress& rNewPos, ScFormulaCell& rOldCell)
     800             : {
     801           0 :     ScFormulaCell* pNew = new ScFormulaCell(rOldCell, *pDoc, rNewPos, SC_CLONECELL_ADJUST3DREL);
     802           0 :     rOldCell.EndListeningTo(pDoc);
     803           0 :     pNew->StartListeningTo(pDoc);
     804           0 :     pNew->SetDirty();
     805           0 :     return pNew;
     806             : }
     807             : 
     808             : }
     809             : 
     810          45 : void ScColumn::SwapRow(SCROW nRow1, SCROW nRow2)
     811             : {
     812          45 :     if (nRow1 == nRow2)
     813             :         // Nothing to swap.
     814          39 :         return;
     815             : 
     816             :     // Ensure that nRow1 < nRow2.
     817          45 :     if (nRow2 < nRow1)
     818           0 :         std::swap(nRow1, nRow2);
     819             : 
     820             :     // Broadcasters (if exist) should NOT be swapped.
     821             : 
     822          45 :     sc::CellStoreType::position_type aPos1 = maCells.position(nRow1);
     823          45 :     if (aPos1.first == maCells.end())
     824           0 :         return;
     825             : 
     826          45 :     sc::CellStoreType::position_type aPos2 = maCells.position(aPos1.first, nRow2);
     827          45 :     if (aPos2.first == maCells.end())
     828           0 :         return;
     829             : 
     830          45 :     std::vector<SCROW> aRows;
     831          45 :     aRows.reserve(2);
     832          45 :     aRows.push_back(nRow1);
     833          45 :     aRows.push_back(nRow2);
     834             : 
     835          45 :     sc::CellStoreType::iterator it1 = aPos1.first, it2 = aPos2.first;
     836             : 
     837          45 :     if (it1->type == it2->type)
     838             :     {
     839             :         // Both positions are of the same type. Do a simple value swap.
     840          36 :         switch (it1->type)
     841             :         {
     842             :             case sc::element_type_empty:
     843             :                 // Both are empty. Nothing to swap.
     844          28 :                 return;
     845             :             case sc::element_type_numeric:
     846             :                 std::swap(
     847           6 :                     sc::numeric_block::at(*it1->data, aPos1.second),
     848          12 :                     sc::numeric_block::at(*it2->data, aPos2.second));
     849           6 :             break;
     850             :             case sc::element_type_string:
     851             :                 std::swap(
     852           2 :                     sc::string_block::at(*it1->data, aPos1.second),
     853           4 :                     sc::string_block::at(*it2->data, aPos2.second));
     854           2 :             break;
     855             :             case sc::element_type_edittext:
     856             :                 std::swap(
     857           0 :                     sc::edittext_block::at(*it1->data, aPos1.second),
     858           0 :                     sc::edittext_block::at(*it2->data, aPos2.second));
     859           0 :             break;
     860             :             case sc::element_type_formula:
     861             :             {
     862             :                 // Swapping of formula cells involve adjustment of references wrt their positions.
     863           0 :                 sc::formula_block::iterator itf1 = sc::formula_block::begin(*it1->data);
     864           0 :                 sc::formula_block::iterator itf2 = sc::formula_block::begin(*it2->data);
     865           0 :                 std::advance(itf1, aPos1.second);
     866           0 :                 std::advance(itf2, aPos2.second);
     867             : 
     868             :                 // TODO: Find out a way to adjust references without cloning new instances.
     869           0 :                 boost::scoped_ptr<ScFormulaCell> pOld1(*itf1);
     870           0 :                 boost::scoped_ptr<ScFormulaCell> pOld2(*itf2);
     871           0 :                 DetouchFormulaCell(aPos1, **itf1);
     872           0 :                 DetouchFormulaCell(aPos2, **itf2);
     873           0 :                 ScFormulaCell* pNew1 = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *pOld2);
     874           0 :                 ScFormulaCell* pNew2 = cloneFormulaCell(pDocument, ScAddress(nCol, nRow2, nTab), *pOld1);
     875           0 :                 *itf1 = pNew1;
     876           0 :                 *itf2 = pNew2;
     877             : 
     878           0 :                 ActivateNewFormulaCell(aPos1, *pNew1);
     879           0 :                 ActivateNewFormulaCell(aPos2, *pNew2);
     880             :             }
     881           0 :             break;
     882             :             default:
     883             :                 ;
     884             :         }
     885             : 
     886           8 :         SwapCellTextAttrs(nRow1, nRow2);
     887           8 :         CellStorageModified();
     888           8 :         BroadcastCells(aRows);
     889           8 :         return;
     890             :     }
     891             : 
     892             :     // The two cells are of different types.
     893             : 
     894           9 :     ScRefCellValue aCell1 = GetCellValue(aPos1.first, aPos1.second);
     895          15 :     ScRefCellValue aCell2 = GetCellValue(aPos2.first, aPos2.second);
     896             : 
     897             :     // Make sure to put cells in row 1 first then row 2!
     898             : 
     899           9 :     if (aCell1.meType == CELLTYPE_NONE)
     900             :     {
     901             :         // cell 1 is empty and cell 2 is not.
     902           3 :         switch (aCell2.meType)
     903             :         {
     904             :             case CELLTYPE_VALUE:
     905           2 :                 it1 = maCells.set(it1, nRow1, aCell2.mfValue); // it2 becomes invalid.
     906           2 :                 maCells.set_empty(it1, nRow2, nRow2);
     907           2 :             break;
     908             :             case CELLTYPE_STRING:
     909           1 :                 it1 = maCells.set(it1, nRow1, *aCell2.mpString);
     910           1 :                 maCells.set_empty(it1, nRow2, nRow2);
     911           1 :             break;
     912             :             case CELLTYPE_EDIT:
     913             :             {
     914           0 :                 it1 = maCells.set(it1, nRow1, aCell2.mpEditText);
     915             :                 EditTextObject* p;
     916           0 :                 maCells.release(it1, nRow2, p);
     917             :             }
     918           0 :             break;
     919             :             case CELLTYPE_FORMULA:
     920             :             {
     921             :                 // cell 1 is empty and cell 2 is a formula cell.
     922           0 :                 ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *aCell2.mpFormula);
     923           0 :                 DetouchFormulaCell(aPos2, *aCell2.mpFormula);
     924           0 :                 it1 = maCells.set(it1, nRow1, pNew);
     925           0 :                 maCells.set_empty(it1, nRow2, nRow2); // original formula cell gets deleted.
     926           0 :                 ActivateNewFormulaCell(it1, nRow1, *pNew);
     927             :             }
     928           0 :             break;
     929             :             default:
     930             :                 ;
     931             :         }
     932             : 
     933           3 :         SwapCellTextAttrs(nRow1, nRow2);
     934           3 :         CellStorageModified();
     935           3 :         BroadcastCells(aRows);
     936           3 :         return;
     937             :     }
     938             : 
     939           6 :     if (aCell2.meType == CELLTYPE_NONE)
     940             :     {
     941             :         // cell 1 is not empty and cell 2 is empty.
     942           0 :         switch (aCell1.meType)
     943             :         {
     944             :             case CELLTYPE_VALUE:
     945             :                 // Value is copied in Cell1.
     946           0 :                 it1 = maCells.set_empty(it1, nRow1, nRow1);
     947           0 :                 maCells.set(it1, nRow2, aCell1.mfValue);
     948           0 :             break;
     949             :             case CELLTYPE_STRING:
     950             :             {
     951           0 :                 OUString aStr = *aCell1.mpString; // make a copy.
     952           0 :                 it1 = maCells.set_empty(it1, nRow1, nRow1); // original string is gone.
     953           0 :                 maCells.set(it1, nRow2, aStr);
     954             :             }
     955           0 :             break;
     956             :             case CELLTYPE_EDIT:
     957             :             {
     958             :                 EditTextObject* p;
     959           0 :                 it1 = maCells.release(it1, nRow1, p);
     960           0 :                 maCells.set(it1, nRow2, p);
     961             :             }
     962           0 :             break;
     963             :             case CELLTYPE_FORMULA:
     964             :             {
     965             :                 // cell 1 is a formula cell and cell 2 is empty.
     966           0 :                 ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow2, nTab), *aCell1.mpFormula);
     967           0 :                 DetouchFormulaCell(aPos1, *aCell1.mpFormula);
     968           0 :                 it1 = maCells.set_empty(it1, nRow1, nRow1); // original formula cell is gone.
     969           0 :                 it1 = maCells.set(it1, nRow2, pNew);
     970           0 :                 ActivateNewFormulaCell(it1, nRow2, *pNew);
     971             :             }
     972           0 :             break;
     973             :             default:
     974             :                 ;
     975             :         }
     976             : 
     977           0 :         SwapCellTextAttrs(nRow1, nRow2);
     978           0 :         CellStorageModified();
     979           0 :         BroadcastCells(aRows);
     980           0 :         return;
     981             :     }
     982             : 
     983             :     // Neither cells are empty, and they are of different types.
     984           6 :     switch (aCell1.meType)
     985             :     {
     986             :         case CELLTYPE_VALUE:
     987             :         {
     988           2 :             switch (aCell2.meType)
     989             :             {
     990             :                 case CELLTYPE_STRING:
     991           2 :                     it1 = maCells.set(it1, nRow1, *aCell2.mpString);
     992           2 :                 break;
     993             :                 case CELLTYPE_EDIT:
     994             :                 {
     995           0 :                     it1 = maCells.set(it1, nRow1, aCell2.mpEditText);
     996             :                     EditTextObject* p;
     997           0 :                     it1 = maCells.release(it1, nRow2, p);
     998             :                 }
     999           0 :                 break;
    1000             :                 case CELLTYPE_FORMULA:
    1001             :                 {
    1002           0 :                     DetouchFormulaCell(aPos2, *aCell2.mpFormula);
    1003           0 :                     ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *aCell2.mpFormula);
    1004           0 :                     it1 = maCells.set(it1, nRow1, pNew);
    1005           0 :                     ActivateNewFormulaCell(it1, nRow1, *pNew);
    1006             :                     // The old formula cell will get overwritten below.
    1007             :                 }
    1008           0 :                 break;
    1009             :                 default:
    1010             :                     ;
    1011             :             }
    1012             : 
    1013           2 :             maCells.set(it1, nRow2, aCell1.mfValue);
    1014             : 
    1015             :         }
    1016           2 :         break;
    1017             :         case CELLTYPE_STRING:
    1018             :         {
    1019           4 :             OUString aStr = *aCell1.mpString; // make a copy.
    1020           4 :             switch (aCell2.meType)
    1021             :             {
    1022             :                 case CELLTYPE_VALUE:
    1023           4 :                     it1 = maCells.set(it1, nRow1, aCell2.mfValue);
    1024           4 :                 break;
    1025             :                 case CELLTYPE_EDIT:
    1026             :                 {
    1027           0 :                     it1 = maCells.set(it1, nRow1, aCell2.mpEditText);
    1028             :                     EditTextObject* p;
    1029           0 :                     it1 = maCells.release(it1, nRow2, p); // prevent it being overwritten.
    1030             :                 }
    1031           0 :                 break;
    1032             :                 case CELLTYPE_FORMULA:
    1033             :                 {
    1034             :                     // cell 1 - string, cell 2 - formula
    1035           0 :                     DetouchFormulaCell(aPos2, *aCell2.mpFormula);
    1036           0 :                     ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *aCell2.mpFormula);
    1037           0 :                     it1 = maCells.set(it1, nRow1, pNew);
    1038           0 :                     ActivateNewFormulaCell(it1, nRow1, *pNew);
    1039             :                     // Old formula cell will get overwritten below.
    1040             :                 }
    1041           0 :                 break;
    1042             :                 default:
    1043             :                     ;
    1044             :             }
    1045             : 
    1046           4 :             maCells.set(it1, nRow2, aStr);
    1047             :         }
    1048           4 :         break;
    1049             :         case CELLTYPE_EDIT:
    1050             :         {
    1051             :             EditTextObject* p;
    1052           0 :             it1 = maCells.release(it1, nRow1, p);
    1053             : 
    1054           0 :             switch (aCell2.meType)
    1055             :             {
    1056             :                 case CELLTYPE_VALUE:
    1057           0 :                     it1 = maCells.set(it1, nRow1, aCell2.mfValue);
    1058           0 :                 break;
    1059             :                 case CELLTYPE_STRING:
    1060           0 :                     it1 = maCells.set(it1, nRow1, *aCell2.mpString);
    1061           0 :                 break;
    1062             :                 case CELLTYPE_FORMULA:
    1063             :                 {
    1064           0 :                     DetouchFormulaCell(aPos2, *aCell2.mpFormula);
    1065           0 :                     ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow1, nTab), *aCell2.mpFormula);
    1066           0 :                     it1 = maCells.set(it1, nRow1, pNew);
    1067           0 :                     ActivateNewFormulaCell(it1, nRow1, *pNew);
    1068             :                     // Old formula cell will get overwritten below.
    1069             :                 }
    1070           0 :                 break;
    1071             :                 default:
    1072             :                     ;
    1073             :             }
    1074             : 
    1075           0 :             maCells.set(it1, nRow2, aCell1.mpEditText);
    1076             :         }
    1077           0 :         break;
    1078             :         case CELLTYPE_FORMULA:
    1079             :         {
    1080             :             // cell 1 is a formula cell and cell 2 is not.
    1081           0 :             DetouchFormulaCell(aPos1, *aCell1.mpFormula);
    1082           0 :             ScFormulaCell* pNew = cloneFormulaCell(pDocument, ScAddress(nCol, nRow2, nTab), *aCell1.mpFormula);
    1083           0 :             switch (aCell2.meType)
    1084             :             {
    1085             :                 case CELLTYPE_VALUE:
    1086           0 :                     it1 = maCells.set(it1, nRow1, aCell2.mfValue);
    1087           0 :                 break;
    1088             :                 case CELLTYPE_STRING:
    1089           0 :                     it1 = maCells.set(it1, nRow1, *aCell2.mpString);
    1090           0 :                 break;
    1091             :                 case CELLTYPE_EDIT:
    1092             :                 {
    1093           0 :                     it1 = maCells.set(it1, nRow1, aCell2.mpEditText);
    1094             :                     EditTextObject* p;
    1095           0 :                     it1 = maCells.release(it1, nRow2, p);
    1096             :                 }
    1097           0 :                 break;
    1098             :                 default:
    1099             :                     ;
    1100             :             }
    1101             : 
    1102           0 :             it1 = maCells.set(it1, nRow2, pNew);
    1103           0 :             ActivateNewFormulaCell(it1, nRow2, *pNew);
    1104             :         }
    1105           0 :         break;
    1106             :         default:
    1107             :             ;
    1108             :     }
    1109             : 
    1110           6 :     SwapCellTextAttrs(nRow1, nRow2);
    1111           6 :     CellStorageModified();
    1112          12 :     BroadcastCells(aRows);
    1113             : }
    1114             : 
    1115             : namespace {
    1116             : 
    1117             : /**
    1118             :  * Adjust references in formula cell with respect to column-wise relocation.
    1119             :  */
    1120           0 : void updateRefInFormulaCell( ScFormulaCell& rCell, SCCOL nCol, SCTAB nTab, SCCOL nColDiff )
    1121             : {
    1122           0 :     ScRange aRange(ScAddress(nCol, 0, nTab), ScAddress(nCol, MAXROW, nTab));
    1123           0 :     rCell.aPos.SetCol(nCol);
    1124           0 :     rCell.UpdateReference(URM_MOVE, aRange, nColDiff, 0, 0);
    1125           0 : }
    1126             : 
    1127             : }
    1128             : 
    1129           0 : void ScColumn::SwapCell( SCROW nRow, ScColumn& rCol)
    1130             : {
    1131           0 :     sc::CellStoreType::position_type aPos1 = maCells.position(nRow);
    1132           0 :     sc::CellStoreType::position_type aPos2 = rCol.maCells.position(nRow);
    1133             : 
    1134           0 :     if (aPos1.first->type == sc::element_type_formula)
    1135             :     {
    1136           0 :         ScFormulaCell& rCell = *sc::formula_block::at(*aPos1.first->data, aPos1.second);
    1137           0 :         updateRefInFormulaCell(rCell, rCol.nCol, nTab, rCol.nCol - nCol);
    1138           0 :         UnshareFormulaCell(aPos1, rCell);
    1139             :     }
    1140             : 
    1141           0 :     if (aPos2.first->type == sc::element_type_formula)
    1142             :     {
    1143           0 :         ScFormulaCell& rCell = *sc::formula_block::at(*aPos2.first->data, aPos2.second);
    1144           0 :         updateRefInFormulaCell(rCell, nCol, nTab, nCol - rCol.nCol);
    1145           0 :         UnshareFormulaCell(aPos2, rCell);
    1146             :     }
    1147             : 
    1148           0 :     maCells.swap(nRow, nRow, rCol.maCells, nRow);
    1149           0 :     maCellTextAttrs.swap(nRow, nRow, rCol.maCellTextAttrs, nRow);
    1150             : 
    1151           0 :     aPos1 = maCells.position(nRow);
    1152           0 :     aPos2 = rCol.maCells.position(nRow);
    1153             : 
    1154           0 :     if (aPos1.first->type == sc::element_type_formula)
    1155             :     {
    1156           0 :         ScFormulaCell& rCell = *sc::formula_block::at(*aPos1.first->data, aPos1.second);
    1157           0 :         JoinNewFormulaCell(aPos1, rCell);
    1158             :     }
    1159             : 
    1160           0 :     if (aPos2.first->type == sc::element_type_formula)
    1161             :     {
    1162           0 :         ScFormulaCell& rCell = *sc::formula_block::at(*aPos2.first->data, aPos2.second);
    1163           0 :         rCol.JoinNewFormulaCell(aPos2, rCell);
    1164             :     }
    1165             : 
    1166           0 :     CellStorageModified();
    1167           0 :     rCol.CellStorageModified();
    1168           0 : }
    1169             : 
    1170             : 
    1171          11 : bool ScColumn::TestInsertCol( SCROW nStartRow, SCROW nEndRow) const
    1172             : {
    1173          11 :     if (IsEmpty())
    1174          11 :         return true;
    1175             : 
    1176             :     // Return false if we have any non-empty cells between nStartRow and nEndRow inclusive.
    1177           0 :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nStartRow);
    1178           0 :     sc::CellStoreType::const_iterator it = aPos.first;
    1179           0 :     if (it->type != sc::element_type_empty)
    1180           0 :         return false;
    1181             : 
    1182             :     // Get the length of the remaining empty segment.
    1183           0 :     size_t nLen = it->size - aPos.second;
    1184           0 :     SCROW nNextNonEmptyRow = nStartRow + nLen;
    1185           0 :     if (nNextNonEmptyRow <= nEndRow)
    1186           0 :         return false;
    1187             : 
    1188             :     //  AttrArray only looks for merged cells
    1189             : 
    1190           0 :     return pAttrArray ? pAttrArray->TestInsertCol(nStartRow, nEndRow) : true;
    1191             : }
    1192             : 
    1193             : 
    1194        9221 : bool ScColumn::TestInsertRow( SCROW nStartRow, SCSIZE nSize ) const
    1195             : {
    1196             :     //  AttrArray only looks for merged cells
    1197             :     {
    1198        9221 :         std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nStartRow);
    1199        9221 :         sc::CellStoreType::const_iterator it = aPos.first;
    1200        9221 :         if (it->type == sc::element_type_empty && maCells.block_size() == 1)
    1201             :             // The entire cell array is empty.
    1202        9211 :             return pAttrArray->TestInsertRow(nSize);
    1203             :     }
    1204             : 
    1205             :     // See if there would be any non-empty cell that gets pushed out.
    1206             : 
    1207             :     // Find the position of the last non-empty cell below nStartRow.
    1208          10 :     size_t nLastNonEmptyRow = MAXROW;
    1209          10 :     sc::CellStoreType::const_reverse_iterator it = maCells.rbegin();
    1210          10 :     if (it->type == sc::element_type_empty)
    1211          10 :         nLastNonEmptyRow -= it->size;
    1212             : 
    1213          10 :     if (nLastNonEmptyRow < static_cast<size_t>(nStartRow))
    1214             :         // No cells would get pushed out.
    1215           6 :         return pAttrArray->TestInsertRow(nSize);
    1216             : 
    1217           4 :     if (nLastNonEmptyRow + nSize > static_cast<size_t>(MAXROW))
    1218             :         // At least one cell would get pushed out. Not good.
    1219           0 :         return false;
    1220             : 
    1221           4 :     return pAttrArray->TestInsertRow(nSize);
    1222             : }
    1223             : 
    1224             : 
    1225        9221 : void ScColumn::InsertRow( SCROW nStartRow, SCSIZE nSize )
    1226             : {
    1227        9221 :     pAttrArray->InsertRow( nStartRow, nSize );
    1228             : 
    1229        9221 :     maBroadcasters.insert_empty(nStartRow, nSize);
    1230        9221 :     maBroadcasters.resize(MAXROWCOUNT);
    1231             : 
    1232        9221 :     maCellTextAttrs.insert_empty(nStartRow, nSize);
    1233        9221 :     maCellTextAttrs.resize(MAXROWCOUNT);
    1234             : 
    1235        9221 :     maCells.insert_empty(nStartRow, nSize);
    1236        9221 :     maCells.resize(MAXROWCOUNT);
    1237             : 
    1238        9221 :     CellStorageModified();
    1239             : 
    1240             :     // We *probably* don't need to broadcast here since the parent call seems
    1241             :     // to take care of it.
    1242        9221 : }
    1243             : 
    1244             : namespace {
    1245             : 
    1246             : class CopyToClipHandler
    1247             : {
    1248             :     const ScColumn& mrSrcCol;
    1249             :     ScColumn& mrDestCol;
    1250             :     sc::ColumnBlockPosition maDestPos;
    1251             :     sc::ColumnBlockPosition* mpDestPos;
    1252             : 
    1253          36 :     void setDefaultAttrsToDest(size_t nRow, size_t nSize)
    1254             :     {
    1255          36 :         std::vector<sc::CellTextAttr> aAttrs(nSize); // default values
    1256          72 :         maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
    1257          72 :             maDestPos.miCellTextAttrPos, nRow, aAttrs.begin(), aAttrs.end());
    1258          36 :     }
    1259             : 
    1260             : public:
    1261          27 :     CopyToClipHandler(const ScColumn& rSrcCol, ScColumn& rDestCol, sc::ColumnBlockPosition* pDestPos) :
    1262          27 :         mrSrcCol(rSrcCol), mrDestCol(rDestCol), mpDestPos(pDestPos)
    1263             :     {
    1264          27 :         if (mpDestPos)
    1265          27 :             maDestPos = *mpDestPos;
    1266             :         else
    1267           0 :             mrDestCol.InitBlockPosition(maDestPos);
    1268          27 :     }
    1269             : 
    1270          27 :     ~CopyToClipHandler()
    1271             :     {
    1272          27 :         if (mpDestPos)
    1273          27 :             *mpDestPos = maDestPos;
    1274          27 :     }
    1275             : 
    1276          47 :     void operator() (const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
    1277             :     {
    1278          47 :         size_t nTopRow = aNode.position + nOffset;
    1279             : 
    1280          47 :         switch (aNode.type)
    1281             :         {
    1282             :             case sc::element_type_numeric:
    1283             :             {
    1284           8 :                 sc::numeric_block::const_iterator it = sc::numeric_block::begin(*aNode.data);
    1285           8 :                 std::advance(it, nOffset);
    1286           8 :                 sc::numeric_block::const_iterator itEnd = it;
    1287           8 :                 std::advance(itEnd, nDataSize);
    1288           8 :                 maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nTopRow, it, itEnd);
    1289           8 :                 setDefaultAttrsToDest(nTopRow, nDataSize);
    1290             :             }
    1291           8 :             break;
    1292             :             case sc::element_type_string:
    1293             :             {
    1294          15 :                 sc::string_block::const_iterator it = sc::string_block::begin(*aNode.data);
    1295          15 :                 std::advance(it, nOffset);
    1296          15 :                 sc::string_block::const_iterator itEnd = it;
    1297          15 :                 std::advance(itEnd, nDataSize);
    1298          15 :                 maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nTopRow, it, itEnd);
    1299          15 :                 setDefaultAttrsToDest(nTopRow, nDataSize);
    1300             :             }
    1301          15 :             break;
    1302             :             case sc::element_type_edittext:
    1303             :             {
    1304           0 :                 sc::edittext_block::const_iterator it = sc::edittext_block::begin(*aNode.data);
    1305           0 :                 std::advance(it, nOffset);
    1306           0 :                 sc::edittext_block::const_iterator itEnd = it;
    1307           0 :                 std::advance(itEnd, nDataSize);
    1308             : 
    1309           0 :                 std::vector<EditTextObject*> aCloned;
    1310           0 :                 aCloned.reserve(nDataSize);
    1311           0 :                 for (; it != itEnd; ++it)
    1312           0 :                     aCloned.push_back(ScEditUtil::Clone(**it, mrDestCol.GetDoc()));
    1313             : 
    1314           0 :                 maDestPos.miCellPos = mrDestCol.GetCellStore().set(
    1315           0 :                     maDestPos.miCellPos, nTopRow, aCloned.begin(), aCloned.end());
    1316             : 
    1317           0 :                 setDefaultAttrsToDest(nTopRow, nDataSize);
    1318             :             }
    1319           0 :             break;
    1320             :             case sc::element_type_formula:
    1321             :             {
    1322          13 :                 sc::formula_block::const_iterator it = sc::formula_block::begin(*aNode.data);
    1323          13 :                 std::advance(it, nOffset);
    1324          13 :                 sc::formula_block::const_iterator itEnd = it;
    1325          13 :                 std::advance(itEnd, nDataSize);
    1326             : 
    1327          13 :                 std::vector<ScFormulaCell*> aCloned;
    1328          13 :                 aCloned.reserve(nDataSize);
    1329          13 :                 ScAddress aDestPos(mrDestCol.GetCol(), nTopRow, mrDestCol.GetTab());
    1330          35 :                 for (; it != itEnd; ++it, aDestPos.IncRow())
    1331             :                 {
    1332          22 :                     const ScFormulaCell& rOld = **it;
    1333          22 :                     if (rOld.GetDirty() && mrSrcCol.GetDoc().GetAutoCalc())
    1334           9 :                         const_cast<ScFormulaCell&>(rOld).Interpret();
    1335             : 
    1336          22 :                     aCloned.push_back(new ScFormulaCell(rOld, mrDestCol.GetDoc(), aDestPos));
    1337             :                 }
    1338             : 
    1339          26 :                 maDestPos.miCellPos = mrDestCol.GetCellStore().set(
    1340          13 :                     maDestPos.miCellPos, nTopRow, aCloned.begin(), aCloned.end());
    1341             : 
    1342          13 :                 setDefaultAttrsToDest(nTopRow, nDataSize);
    1343             :             }
    1344          13 :             break;
    1345             :             default:
    1346             :                 ;
    1347             :         }
    1348          47 :     }
    1349             : };
    1350             : 
    1351             : }
    1352             : 
    1353          27 : void ScColumn::CopyToClip(
    1354             :     sc::CopyToClipContext& rCxt, SCROW nRow1, SCROW nRow2, ScColumn& rColumn ) const
    1355             : {
    1356             :     pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray,
    1357          27 :                           rCxt.isKeepScenarioFlags() ? (SC_MF_ALL & ~SC_MF_SCENARIO) : SC_MF_ALL );
    1358             : 
    1359          27 :     CopyToClipHandler aFunc(*this, rColumn, rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol));
    1360          27 :     sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
    1361          27 :     rColumn.RegroupFormulaCells(nRow1, nRow2);
    1362          27 :     rColumn.CellStorageModified();
    1363          27 : }
    1364             : 
    1365           3 : void ScColumn::CopyStaticToDocument(SCROW nRow1, SCROW nRow2, ScColumn& rDestCol)
    1366             : {
    1367           3 :     if (nRow1 > nRow2)
    1368           3 :         return;
    1369             : 
    1370           3 :     sc::ColumnBlockPosition aDestPos;
    1371           3 :     CopyCellTextAttrsToDocument(nRow1, nRow2, rDestCol);
    1372             : 
    1373             :     // First, clear the destination column for the specified row range.
    1374           3 :     rDestCol.maCells.set_empty(nRow1, nRow2);
    1375             : 
    1376           3 :     aDestPos.miCellPos = rDestCol.maCells.begin();
    1377             : 
    1378           3 :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow1);
    1379           3 :     sc::CellStoreType::const_iterator it = aPos.first;
    1380           3 :     size_t nOffset = aPos.second;
    1381           3 :     size_t nDataSize = 0;
    1382           3 :     size_t nCurRow = nRow1;
    1383             : 
    1384           6 :     for (; it != maCells.end() && nCurRow <= static_cast<size_t>(nRow2); ++it, nOffset = 0, nCurRow += nDataSize)
    1385             :     {
    1386           4 :         bool bLastBlock = false;
    1387           4 :         nDataSize = it->size - nOffset;
    1388           4 :         if (nCurRow + nDataSize - 1 > static_cast<size_t>(nRow2))
    1389             :         {
    1390             :             // Truncate the block to copy to clipboard.
    1391           1 :             nDataSize = nRow2 - nCurRow + 1;
    1392           1 :             bLastBlock = true;
    1393             :         }
    1394             : 
    1395           4 :         switch (it->type)
    1396             :         {
    1397             :             case sc::element_type_numeric:
    1398             :             {
    1399           1 :                 sc::numeric_block::const_iterator itData = sc::numeric_block::begin(*it->data);
    1400           1 :                 std::advance(itData, nOffset);
    1401           1 :                 sc::numeric_block::const_iterator itDataEnd = itData;
    1402           1 :                 std::advance(itDataEnd, nDataSize);
    1403           1 :                 aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nCurRow, itData, itDataEnd);
    1404             :             }
    1405           1 :             break;
    1406             :             case sc::element_type_string:
    1407             :             {
    1408           1 :                 sc::string_block::const_iterator itData = sc::string_block::begin(*it->data);
    1409           1 :                 std::advance(itData, nOffset);
    1410           1 :                 sc::string_block::const_iterator itDataEnd = itData;
    1411           1 :                 std::advance(itDataEnd, nDataSize);
    1412           1 :                 aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nCurRow, itData, itDataEnd);
    1413             :             }
    1414           1 :             break;
    1415             :             case sc::element_type_edittext:
    1416             :             {
    1417           0 :                 sc::edittext_block::const_iterator itData = sc::edittext_block::begin(*it->data);
    1418           0 :                 std::advance(itData, nOffset);
    1419           0 :                 sc::edittext_block::const_iterator itDataEnd = itData;
    1420           0 :                 std::advance(itDataEnd, nDataSize);
    1421             : 
    1422             :                 // Convert to simple strings.
    1423           0 :                 std::vector<OUString> aConverted;
    1424           0 :                 aConverted.reserve(nDataSize);
    1425           0 :                 for (; itData != itDataEnd; ++itData)
    1426             :                 {
    1427           0 :                     const EditTextObject& rObj = **itData;
    1428           0 :                     aConverted.push_back(ScEditUtil::GetString(rObj));
    1429             :                 }
    1430           0 :                 aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nCurRow, aConverted.begin(), aConverted.end());
    1431             :             }
    1432           0 :             break;
    1433             :             case sc::element_type_formula:
    1434             :             {
    1435           1 :                 sc::formula_block::const_iterator itData = sc::formula_block::begin(*it->data);
    1436           1 :                 std::advance(itData, nOffset);
    1437           1 :                 sc::formula_block::const_iterator itDataEnd = itData;
    1438           1 :                 std::advance(itDataEnd, nDataSize);
    1439             : 
    1440             :                 // Interpret and convert to raw values.
    1441           2 :                 for (SCROW i = 0; itData != itDataEnd; ++itData, ++i)
    1442             :                 {
    1443           1 :                     SCROW nRow = nCurRow + i;
    1444             : 
    1445           1 :                     ScFormulaCell& rFC = const_cast<ScFormulaCell&>(**itData);
    1446           1 :                     if (rFC.GetDirty() && pDocument->GetAutoCalc())
    1447           0 :                         rFC.Interpret();
    1448             : 
    1449           1 :                     if (rFC.GetErrCode())
    1450             :                         // Skip cells with error.
    1451           0 :                         break;
    1452             : 
    1453           1 :                     if (rFC.IsValue())
    1454           1 :                         aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nRow, rFC.GetValue());
    1455             :                     else
    1456           0 :                         aDestPos.miCellPos = rDestCol.maCells.set(aDestPos.miCellPos, nRow, rFC.GetString());
    1457             :                 }
    1458             :             }
    1459           1 :             break;
    1460             :             default:
    1461             :                 ;
    1462             :         }
    1463             : 
    1464           4 :         if (bLastBlock)
    1465           1 :             break;
    1466             :     }
    1467             : 
    1468           3 :     rDestCol.RegroupFormulaCells(nRow1, nRow2);
    1469           3 :     rDestCol.CellStorageModified();
    1470             : }
    1471             : 
    1472           0 : void ScColumn::CopyCellToDocument( SCROW nSrcRow, SCROW nDestRow, ScColumn& rDestCol )
    1473             : {
    1474           0 :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nSrcRow);
    1475           0 :     sc::CellStoreType::const_iterator it = aPos.first;
    1476           0 :     bool bSet = true;
    1477           0 :     switch (it->type)
    1478             :     {
    1479             :         case sc::element_type_numeric:
    1480           0 :             rDestCol.maCells.set(nDestRow, sc::numeric_block::at(*it->data, aPos.second));
    1481           0 :         break;
    1482             :         case sc::element_type_string:
    1483           0 :             rDestCol.maCells.set(nDestRow, sc::string_block::at(*it->data, aPos.second));
    1484           0 :         break;
    1485             :         case sc::element_type_edittext:
    1486             :         {
    1487           0 :             EditTextObject* p = sc::edittext_block::at(*it->data, aPos.second);
    1488           0 :             if (pDocument == rDestCol.pDocument)
    1489           0 :                 rDestCol.maCells.set(nDestRow, p->Clone());
    1490             :             else
    1491           0 :                 rDestCol.maCells.set(nDestRow, ScEditUtil::Clone(*p, *rDestCol.pDocument));
    1492             :         }
    1493           0 :         break;
    1494             :         case sc::element_type_formula:
    1495             :         {
    1496           0 :             ScFormulaCell* p = sc::formula_block::at(*it->data, aPos.second);
    1497           0 :             if (p->GetDirty() && pDocument->GetAutoCalc())
    1498           0 :                 p->Interpret();
    1499             : 
    1500           0 :             ScAddress aDestPos = p->aPos;
    1501           0 :             aDestPos.SetRow(nDestRow);
    1502           0 :             ScFormulaCell* pNew = new ScFormulaCell(*p, *rDestCol.pDocument, aDestPos);
    1503           0 :             rDestCol.maCells.set(nDestRow, pNew);
    1504             :         }
    1505           0 :         break;
    1506             :         case sc::element_type_empty:
    1507             :         default:
    1508             :             // empty
    1509           0 :             rDestCol.maCells.set_empty(nDestRow, nDestRow);
    1510           0 :             bSet = false;
    1511             :     }
    1512             : 
    1513           0 :     if (bSet)
    1514           0 :         rDestCol.maCellTextAttrs.set(nDestRow, maCellTextAttrs.get<sc::CellTextAttr>(nSrcRow));
    1515             :     else
    1516           0 :         rDestCol.maCellTextAttrs.set_empty(nDestRow, nDestRow);
    1517             : 
    1518           0 :     rDestCol.RegroupFormulaCells(nDestRow);
    1519           0 :     rDestCol.CellStorageModified();
    1520           0 : }
    1521             : 
    1522             : namespace {
    1523             : 
    1524        1122 : bool canCopyValue(const ScDocument& rDoc, const ScAddress& rPos, sal_uInt16 nFlags)
    1525             : {
    1526        1122 :     sal_uInt32 nNumIndex = static_cast<const SfxUInt32Item*>(rDoc.GetAttr(rPos, ATTR_VALUE_FORMAT))->GetValue();
    1527        1122 :     short nType = rDoc.GetFormatTable()->GetType(nNumIndex);
    1528        1122 :     if ((nType == NUMBERFORMAT_DATE) || (nType == NUMBERFORMAT_TIME) || (nType == NUMBERFORMAT_DATETIME))
    1529           0 :         return ((nFlags & IDF_DATETIME) != 0);
    1530             : 
    1531        1122 :     return ((nFlags & IDF_VALUE) != 0);
    1532             : }
    1533             : 
    1534             : class CopyAsLinkHandler
    1535             : {
    1536             :     const ScColumn& mrSrcCol;
    1537             :     ScColumn& mrDestCol;
    1538             :     sc::ColumnBlockPosition maDestPos;
    1539             :     sc::ColumnBlockPosition* mpDestPos;
    1540             :     sal_uInt16 mnCopyFlags;
    1541             :     std::vector<ScFormulaCell*> maCellBuffer;
    1542             : 
    1543           0 :     void setDefaultAttrToDest(size_t nRow)
    1544             :     {
    1545           0 :         maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
    1546           0 :             maDestPos.miCellTextAttrPos, nRow, sc::CellTextAttr());
    1547           0 :     }
    1548             : 
    1549           0 :     void setDefaultAttrsToDest(size_t nRow, size_t nSize)
    1550             :     {
    1551           0 :         std::vector<sc::CellTextAttr> aAttrs(nSize); // default values
    1552           0 :         maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
    1553           0 :             maDestPos.miCellTextAttrPos, nRow, aAttrs.begin(), aAttrs.end());
    1554           0 :     }
    1555             : 
    1556           0 :     ScFormulaCell* createRefCell(size_t nRow)
    1557             :     {
    1558             :         ScSingleRefData aRef;
    1559           0 :         aRef.InitAddress(ScAddress(mrSrcCol.GetCol(), nRow, mrSrcCol.GetTab())); // Absolute reference.
    1560           0 :         aRef.SetFlag3D(true);
    1561             : 
    1562           0 :         ScTokenArray aArr;
    1563           0 :         aArr.AddSingleReference(aRef);
    1564           0 :         return new ScFormulaCell(&mrDestCol.GetDoc(), ScAddress(mrDestCol.GetCol(), nRow, mrDestCol.GetTab()), &aArr);
    1565             :     }
    1566             : 
    1567           0 :     void createRefBlock(const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
    1568             :     {
    1569           0 :         size_t nTopRow = aNode.position + nOffset;
    1570             : 
    1571           0 :         maCellBuffer.clear();
    1572           0 :         maCellBuffer.reserve(nDataSize);
    1573             : 
    1574           0 :         for (size_t i = 0; i < nDataSize; ++i)
    1575           0 :             maCellBuffer.push_back(createRefCell(nTopRow + i));
    1576             : 
    1577           0 :         maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nTopRow, maCellBuffer.begin(), maCellBuffer.end());
    1578           0 :         setDefaultAttrsToDest(nTopRow, nDataSize);
    1579           0 :     }
    1580             : 
    1581             : public:
    1582           0 :     CopyAsLinkHandler(const ScColumn& rSrcCol, ScColumn& rDestCol, sc::ColumnBlockPosition* pDestPos, sal_uInt16 nCopyFlags) :
    1583           0 :         mrSrcCol(rSrcCol), mrDestCol(rDestCol), mpDestPos(pDestPos), mnCopyFlags(nCopyFlags)
    1584             :     {
    1585           0 :         if (mpDestPos)
    1586           0 :             maDestPos = *mpDestPos;
    1587           0 :     }
    1588             : 
    1589           0 :     ~CopyAsLinkHandler()
    1590           0 :     {
    1591           0 :         if (mpDestPos)
    1592           0 :             *mpDestPos = maDestPos;
    1593           0 :     }
    1594             : 
    1595           0 :     void operator() (const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
    1596             :     {
    1597           0 :         size_t nRow = aNode.position + nOffset;
    1598             : 
    1599           0 :         switch (aNode.type)
    1600             :         {
    1601             :             case sc::element_type_numeric:
    1602             :             {
    1603           0 :                 if ((mnCopyFlags & (IDF_DATETIME|IDF_VALUE)) == 0)
    1604           0 :                     return;
    1605             : 
    1606           0 :                 sc::numeric_block::const_iterator it = sc::numeric_block::begin(*aNode.data);
    1607           0 :                 std::advance(it, nOffset);
    1608           0 :                 sc::numeric_block::const_iterator itEnd = it;
    1609           0 :                 std::advance(itEnd, nDataSize);
    1610             : 
    1611           0 :                 ScAddress aSrcPos(mrSrcCol.GetCol(), nRow, mrSrcCol.GetTab());
    1612           0 :                 for (; it != itEnd; ++it, aSrcPos.IncRow(), ++nRow)
    1613             :                 {
    1614           0 :                     if (!canCopyValue(mrSrcCol.GetDoc(), aSrcPos, mnCopyFlags))
    1615           0 :                         continue;
    1616             : 
    1617           0 :                     maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, createRefCell(nRow));
    1618           0 :                     setDefaultAttrToDest(nRow);
    1619             :                 }
    1620             :             }
    1621           0 :             break;
    1622             :             case sc::element_type_string:
    1623             :             case sc::element_type_edittext:
    1624             :             {
    1625           0 :                 if (!(mnCopyFlags & IDF_STRING))
    1626           0 :                     return;
    1627             : 
    1628           0 :                 createRefBlock(aNode, nOffset, nDataSize);
    1629             :             }
    1630           0 :             break;
    1631             :             case sc::element_type_formula:
    1632             :             {
    1633           0 :                 if (!(mnCopyFlags & IDF_FORMULA))
    1634           0 :                     return;
    1635             : 
    1636           0 :                 createRefBlock(aNode, nOffset, nDataSize);
    1637             :             }
    1638           0 :             break;
    1639             :             default:
    1640             :                 ;
    1641             :         }
    1642             :     }
    1643             : };
    1644             : 
    1645             : class CopyByCloneHandler
    1646             : {
    1647             :     const ScColumn& mrSrcCol;
    1648             :     ScColumn& mrDestCol;
    1649             :     sc::ColumnBlockPosition maDestPos;
    1650             :     sc::ColumnBlockPosition* mpDestPos;
    1651             :     sal_uInt16 mnCopyFlags;
    1652             : 
    1653        2225 :     void setDefaultAttrToDest(size_t nRow)
    1654             :     {
    1655        4450 :         maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
    1656        2225 :             maDestPos.miCellTextAttrPos, nRow, sc::CellTextAttr());
    1657        2225 :     }
    1658             : 
    1659           2 :     void setDefaultAttrsToDest(size_t nRow, size_t nSize)
    1660             :     {
    1661           2 :         std::vector<sc::CellTextAttr> aAttrs(nSize); // default values
    1662           4 :         maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set(
    1663           4 :             maDestPos.miCellTextAttrPos, nRow, aAttrs.begin(), aAttrs.end());
    1664           2 :     }
    1665             : 
    1666         156 :     void cloneFormulaCell(size_t nRow, ScFormulaCell& rSrcCell)
    1667             :     {
    1668         156 :         ScAddress aDestPos(mrDestCol.GetCol(), nRow, mrDestCol.GetTab());
    1669             : 
    1670         156 :         bool bCloneValue          = (mnCopyFlags & IDF_VALUE) != 0;
    1671         156 :         bool bCloneDateTime       = (mnCopyFlags & IDF_DATETIME) != 0;
    1672         156 :         bool bCloneString         = (mnCopyFlags & IDF_STRING) != 0;
    1673         156 :         bool bCloneSpecialBoolean = (mnCopyFlags & IDF_SPECIAL_BOOLEAN) != 0;
    1674         156 :         bool bCloneFormula        = (mnCopyFlags & IDF_FORMULA) != 0;
    1675             : 
    1676         156 :         bool bForceFormula = false;
    1677             : 
    1678         156 :         if (bCloneSpecialBoolean)
    1679             :         {
    1680             :             // See if the formula consists of =TRUE() or =FALSE().
    1681           0 :             ScTokenArray* pCode = rSrcCell.GetCode();
    1682           0 :             if (pCode && pCode->GetLen() == 1)
    1683             :             {
    1684           0 :                 const formula::FormulaToken* p = pCode->First();
    1685           0 :                 if (p->GetOpCode() == ocTrue || p->GetOpCode() == ocFalse)
    1686             :                     // This is a boolean formula.
    1687           0 :                     bForceFormula = true;
    1688             :             }
    1689             :         }
    1690             : 
    1691         156 :         if (bForceFormula || bCloneFormula)
    1692             :         {
    1693             :             // Clone as formula cell.
    1694         156 :             ScFormulaCell* pCell = new ScFormulaCell(rSrcCell, mrDestCol.GetDoc(), aDestPos);
    1695         156 :             pCell->SetDirtyVar();
    1696         156 :             maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, pCell);
    1697         156 :             setDefaultAttrToDest(nRow);
    1698         156 :             return;
    1699             :         }
    1700             : 
    1701           0 :         if (mrDestCol.GetDoc().IsUndo())
    1702           0 :             return;
    1703             : 
    1704           0 :         if (bCloneValue)
    1705             :         {
    1706           0 :             sal_uInt16 nErr = rSrcCell.GetErrCode();
    1707           0 :             if (nErr)
    1708             :             {
    1709             :                 // error codes are cloned with values
    1710           0 :                 ScFormulaCell* pErrCell = new ScFormulaCell(&mrDestCol.GetDoc(), aDestPos);
    1711           0 :                 pErrCell->SetErrCode(nErr);
    1712           0 :                 maDestPos.miCellPos = mrDestCol.GetCellStore().set(
    1713           0 :                     maDestPos.miCellPos, nRow, new ScFormulaCell(rSrcCell, mrDestCol.GetDoc(), aDestPos));
    1714           0 :                 setDefaultAttrToDest(nRow);
    1715           0 :                 return;
    1716             :             }
    1717             :         }
    1718             : 
    1719           0 :         if (bCloneValue || bCloneDateTime)
    1720             :         {
    1721           0 :             if (rSrcCell.IsValue())
    1722             :             {
    1723           0 :                 if (canCopyValue(mrSrcCol.GetDoc(), ScAddress(mrSrcCol.GetCol(), nRow, mrSrcCol.GetTab()), mnCopyFlags))
    1724             :                 {
    1725           0 :                     maDestPos.miCellPos = mrDestCol.GetCellStore().set(
    1726           0 :                         maDestPos.miCellPos, nRow, rSrcCell.GetValue());
    1727           0 :                     setDefaultAttrToDest(nRow);
    1728             :                 }
    1729             : 
    1730           0 :                 return;
    1731             :             }
    1732             :         }
    1733             : 
    1734           0 :         if (bCloneString)
    1735             :         {
    1736           0 :             OUString aStr = rSrcCell.GetString();
    1737           0 :             if (aStr.isEmpty())
    1738             :                 // Don't create empty string cells.
    1739           0 :                 return;
    1740             : 
    1741           0 :             if (rSrcCell.IsMultilineResult())
    1742             :             {
    1743             :                 // Clone as an edit text object.
    1744           0 :                 EditEngine& rEngine = mrDestCol.GetDoc().GetEditEngine();
    1745           0 :                 rEngine.SetText(aStr);
    1746           0 :                 maDestPos.miCellPos =
    1747           0 :                     mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, rEngine.CreateTextObject());
    1748             :             }
    1749             :             else
    1750             :             {
    1751           0 :                 maDestPos.miCellPos =
    1752           0 :                     mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, aStr);
    1753             :             }
    1754             : 
    1755           0 :             setDefaultAttrToDest(nRow);
    1756             :         }
    1757             :     }
    1758             : 
    1759             : public:
    1760       79951 :     CopyByCloneHandler(const ScColumn& rSrcCol, ScColumn& rDestCol, sc::ColumnBlockPosition* pDestPos, sal_uInt16 nCopyFlags) :
    1761       79951 :         mrSrcCol(rSrcCol), mrDestCol(rDestCol), mpDestPos(pDestPos), mnCopyFlags(nCopyFlags)
    1762             :     {
    1763       79951 :         if (mpDestPos)
    1764       79951 :             maDestPos = *mpDestPos;
    1765       79951 :     }
    1766             : 
    1767       79951 :     ~CopyByCloneHandler()
    1768             :     {
    1769       79951 :         if (mpDestPos)
    1770       79951 :             *mpDestPos = maDestPos;
    1771       79951 :     }
    1772             : 
    1773       81560 :     void operator() (const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
    1774             :     {
    1775       81560 :         size_t nRow = aNode.position + nOffset;
    1776             : 
    1777       81560 :         switch (aNode.type)
    1778             :         {
    1779             :             case sc::element_type_numeric:
    1780             :             {
    1781         716 :                 if ((mnCopyFlags & (IDF_DATETIME|IDF_VALUE)) == 0)
    1782         118 :                     return;
    1783             : 
    1784         598 :                 sc::numeric_block::const_iterator it = sc::numeric_block::begin(*aNode.data);
    1785         598 :                 std::advance(it, nOffset);
    1786         598 :                 sc::numeric_block::const_iterator itEnd = it;
    1787         598 :                 std::advance(itEnd, nDataSize);
    1788             : 
    1789         598 :                 ScAddress aSrcPos(mrSrcCol.GetCol(), nRow, mrSrcCol.GetTab());
    1790        1720 :                 for (; it != itEnd; ++it, aSrcPos.IncRow(), ++nRow)
    1791             :                 {
    1792        1122 :                     if (!canCopyValue(mrSrcCol.GetDoc(), aSrcPos, mnCopyFlags))
    1793           0 :                         continue;
    1794             : 
    1795        1122 :                     maDestPos.miCellPos = mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, *it);
    1796        1122 :                     setDefaultAttrToDest(nRow);
    1797             :                 }
    1798             :             }
    1799         598 :             break;
    1800             :             case sc::element_type_string:
    1801             :             {
    1802         520 :                 if (!(mnCopyFlags & IDF_STRING))
    1803         101 :                     return;
    1804             : 
    1805         419 :                 sc::string_block::const_iterator it = sc::string_block::begin(*aNode.data);
    1806         419 :                 std::advance(it, nOffset);
    1807         419 :                 sc::string_block::const_iterator itEnd = it;
    1808         419 :                 std::advance(itEnd, nDataSize);
    1809             : 
    1810        1366 :                 for (; it != itEnd; ++it, ++nRow)
    1811             :                 {
    1812         947 :                     const OUString& rStr = *it;
    1813         947 :                     if (rStr.isEmpty())
    1814             :                     {
    1815             :                         // String cell with empty value is used to special-case cell value removal.
    1816           0 :                         maDestPos.miCellPos = mrDestCol.GetCellStore().set_empty(
    1817           0 :                             maDestPos.miCellPos, nRow, nRow);
    1818           0 :                         maDestPos.miCellTextAttrPos = mrDestCol.GetCellAttrStore().set_empty(
    1819           0 :                             maDestPos.miCellTextAttrPos, nRow, nRow);
    1820             :                     }
    1821             :                     else
    1822             :                     {
    1823        2841 :                         maDestPos.miCellPos =
    1824        1894 :                             mrDestCol.GetCellStore().set(maDestPos.miCellPos, nRow, rStr);
    1825         947 :                         setDefaultAttrToDest(nRow);
    1826             :                     }
    1827             :                 }
    1828             :             }
    1829         419 :             break;
    1830             :             case sc::element_type_edittext:
    1831             :             {
    1832           2 :                 if (!(mnCopyFlags & IDF_STRING))
    1833           0 :                     return;
    1834             : 
    1835           2 :                 sc::edittext_block::const_iterator it = sc::edittext_block::begin(*aNode.data);
    1836           2 :                 std::advance(it, nOffset);
    1837           2 :                 sc::edittext_block::const_iterator itEnd = it;
    1838           2 :                 std::advance(itEnd, nDataSize);
    1839             : 
    1840           2 :                 std::vector<EditTextObject*> aCloned;
    1841           2 :                 aCloned.reserve(nDataSize);
    1842           4 :                 for (; it != itEnd; ++it)
    1843           2 :                     aCloned.push_back(ScEditUtil::Clone(**it, mrDestCol.GetDoc()));
    1844             : 
    1845           4 :                 maDestPos.miCellPos = mrDestCol.GetCellStore().set(
    1846           2 :                     maDestPos.miCellPos, nRow, aCloned.begin(), aCloned.end());
    1847             : 
    1848           2 :                 setDefaultAttrsToDest(nRow, nDataSize);
    1849             :             }
    1850           2 :             break;
    1851             :             case sc::element_type_formula:
    1852             :             {
    1853          73 :                 sc::formula_block::const_iterator it = sc::formula_block::begin(*aNode.data);
    1854          73 :                 std::advance(it, nOffset);
    1855          73 :                 sc::formula_block::const_iterator itEnd = it;
    1856          73 :                 std::advance(itEnd, nDataSize);
    1857             : 
    1858         229 :                 for (; it != itEnd; ++it, ++nRow)
    1859         156 :                     cloneFormulaCell(nRow, const_cast<ScFormulaCell&>(**it));
    1860             :             }
    1861          73 :             break;
    1862             :             default:
    1863             :                 ;
    1864             :         }
    1865             :     }
    1866             : };
    1867             : 
    1868             : }
    1869             : 
    1870       82937 : void ScColumn::CopyToColumn(
    1871             :     sc::CopyToDocContext& rCxt,
    1872             :     SCROW nRow1, SCROW nRow2, sal_uInt16 nFlags, bool bMarked, ScColumn& rColumn,
    1873             :     const ScMarkData* pMarkData, bool bAsLink) const
    1874             : {
    1875       82937 :     if (bMarked)
    1876             :     {
    1877             :         SCROW nStart, nEnd;
    1878        1458 :         if (pMarkData && pMarkData->IsMultiMarked())
    1879             :         {
    1880        1458 :             ScMarkArrayIter aIter( pMarkData->GetArray()+nCol );
    1881             : 
    1882        3364 :             while ( aIter.Next( nStart, nEnd ) && nStart <= nRow2 )
    1883             :             {
    1884         448 :                 if ( nEnd >= nRow1 )
    1885         896 :                     CopyToColumn(rCxt, std::max(nRow1,nStart), std::min(nRow2,nEnd),
    1886        1344 :                                     nFlags, false, rColumn, pMarkData, bAsLink );
    1887        1458 :             }
    1888             :         }
    1889             :         else
    1890             :         {
    1891             :             OSL_FAIL("CopyToColumn: bMarked, but no mark");
    1892             :         }
    1893       84395 :         return;
    1894             :     }
    1895             : 
    1896       81479 :     if ( (nFlags & IDF_ATTRIB) != 0 )
    1897             :     {
    1898       46281 :         if ( (nFlags & IDF_STYLES) != IDF_STYLES )
    1899             :         {   // keep the StyleSheets in the target document
    1900             :             // e.g. DIF and RTF Clipboard-Import
    1901           0 :             for ( SCROW nRow = nRow1; nRow <= nRow2; nRow++ )
    1902             :             {
    1903             :                 const ScStyleSheet* pStyle =
    1904           0 :                     rColumn.pAttrArray->GetPattern( nRow )->GetStyleSheet();
    1905           0 :                 const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow );
    1906           0 :                 ScPatternAttr* pNewPattern = new ScPatternAttr( *pPattern );
    1907           0 :                 pNewPattern->SetStyleSheet( (ScStyleSheet*)pStyle );
    1908           0 :                 rColumn.pAttrArray->SetPattern( nRow, pNewPattern, true );
    1909           0 :                 delete pNewPattern;
    1910             :             }
    1911             :         }
    1912             :         else
    1913       46281 :             pAttrArray->CopyArea( nRow1, nRow2, 0, *rColumn.pAttrArray);
    1914             :     }
    1915             : 
    1916       81479 :     if ((nFlags & IDF_CONTENTS) != 0)
    1917             :     {
    1918       79951 :         if (bAsLink)
    1919             :         {
    1920           0 :             CopyAsLinkHandler aFunc(*this, rColumn, rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol), nFlags);
    1921           0 :             sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
    1922             :         }
    1923             :         else
    1924             :         {
    1925       79951 :             CopyByCloneHandler aFunc(*this, rColumn, rCxt.getBlockPosition(rColumn.nTab, rColumn.nCol), nFlags);
    1926       79951 :             sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2);
    1927             :         }
    1928             : 
    1929       79951 :         rColumn.RegroupFormulaCells(nRow1, nRow2);
    1930       79951 :         rColumn.CellStorageModified();
    1931             :     }
    1932             : }
    1933             : 
    1934             : 
    1935           6 : void ScColumn::UndoToColumn(
    1936             :     sc::CopyToDocContext& rCxt, SCROW nRow1, SCROW nRow2, sal_uInt16 nFlags, bool bMarked,
    1937             :     ScColumn& rColumn, const ScMarkData* pMarkData ) const
    1938             : {
    1939           6 :     if (nRow1 > 0)
    1940           6 :         CopyToColumn(rCxt, 0, nRow1-1, IDF_FORMULA, false, rColumn);
    1941             : 
    1942           6 :     CopyToColumn(rCxt, nRow1, nRow2, nFlags, bMarked, rColumn, pMarkData);      //! bMarked ????
    1943             : 
    1944           6 :     if (nRow2 < MAXROW)
    1945           6 :         CopyToColumn(rCxt, nRow2+1, MAXROW, IDF_FORMULA, false, rColumn);
    1946           6 : }
    1947             : 
    1948             : 
    1949           0 : void ScColumn::CopyUpdated( const ScColumn& rPosCol, ScColumn& rDestCol ) const
    1950             : {
    1951             :     // Copy cells from this column to the destination column only for those
    1952             :     // rows that are present in the position column (rPosCol).
    1953             : 
    1954             :     // First, mark all the non-empty cell ranges from the position column.
    1955           0 :     sc::SingleColumnSpanSet aRangeSet;
    1956           0 :     aRangeSet.scan(rPosCol);
    1957             : 
    1958             :     // Now, copy cells from this column to the destination column for those
    1959             :     // marked row ranges.
    1960           0 :     sc::SingleColumnSpanSet::SpansType aRanges;
    1961           0 :     aRangeSet.getSpans(aRanges);
    1962             : 
    1963           0 :     CopyToClipHandler aFunc(*this, rDestCol, NULL);
    1964           0 :     sc::CellStoreType::const_iterator itPos = maCells.begin();
    1965           0 :     sc::SingleColumnSpanSet::SpansType::const_iterator it = aRanges.begin(), itEnd = aRanges.end();
    1966           0 :     for (; it != itEnd; ++it)
    1967             :     {
    1968           0 :         itPos = sc::ParseBlock(itPos, maCells, aFunc, it->mnRow1, it->mnRow2);
    1969           0 :         rDestCol.RegroupFormulaCells(it->mnRow1, it->mnRow2);
    1970             :     }
    1971             : 
    1972           0 :     rDestCol.CellStorageModified();
    1973           0 : }
    1974             : 
    1975             : 
    1976           0 : void ScColumn::CopyScenarioFrom( const ScColumn& rSrcCol )
    1977             : {
    1978             :     //  This is the scenario table, the data is copied into it
    1979           0 :     sc::CopyToDocContext aCxt(*pDocument);
    1980           0 :     ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
    1981           0 :     SCROW nStart = -1, nEnd = -1;
    1982           0 :     const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
    1983           0 :     while (pPattern)
    1984             :     {
    1985           0 :         if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
    1986             :         {
    1987           0 :             DeleteArea( nStart, nEnd, IDF_CONTENTS );
    1988             :             ((ScColumn&)rSrcCol).
    1989           0 :                 CopyToColumn(aCxt, nStart, nEnd, IDF_CONTENTS, false, *this);
    1990             : 
    1991             :             //  UpdateUsed not needed, already done in TestCopyScenario (obsolete comment ?)
    1992             : 
    1993           0 :             SCsTAB nDz = nTab - rSrcCol.nTab;
    1994             :             UpdateReference(
    1995           0 :                 URM_COPY, ScRange(nCol, nStart, nTab, nCol, nEnd, nTab), 0, 0, nDz, NULL);
    1996           0 :             UpdateCompile();
    1997             :         }
    1998             : 
    1999             :         //! make CopyToColumn "const" !!! (obsolete comment ?)
    2000             : 
    2001           0 :         pPattern = aAttrIter.Next( nStart, nEnd );
    2002           0 :     }
    2003           0 : }
    2004             : 
    2005             : 
    2006           0 : void ScColumn::CopyScenarioTo( ScColumn& rDestCol ) const
    2007             : {
    2008             :     //  This is the scenario table, the data is copied to the other
    2009           0 :     sc::CopyToDocContext aCxt(*rDestCol.pDocument);
    2010           0 :     ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
    2011           0 :     SCROW nStart = -1, nEnd = -1;
    2012           0 :     const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
    2013           0 :     while (pPattern)
    2014             :     {
    2015           0 :         if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
    2016             :         {
    2017           0 :             rDestCol.DeleteArea( nStart, nEnd, IDF_CONTENTS );
    2018             :             ((ScColumn*)this)->
    2019           0 :                 CopyToColumn(aCxt, nStart, nEnd, IDF_CONTENTS, false, rDestCol);
    2020             : 
    2021             :             //  UpdateUsed not needed, is already done in TestCopyScenario (obsolete comment ?)
    2022             : 
    2023           0 :             SCsTAB nDz = rDestCol.nTab - nTab;
    2024             :             rDestCol.UpdateReference(
    2025             :                 URM_COPY, ScRange(rDestCol.nCol, nStart, rDestCol.nTab, rDestCol.nCol, nEnd, rDestCol.nTab),
    2026           0 :                 0, 0, nDz, NULL);
    2027           0 :             rDestCol.UpdateCompile();
    2028             :         }
    2029             : 
    2030             :         //! make CopyToColumn "const" !!! (obsolete comment ?)
    2031             : 
    2032           0 :         pPattern = aAttrIter.Next( nStart, nEnd );
    2033           0 :     }
    2034           0 : }
    2035             : 
    2036             : 
    2037           0 : bool ScColumn::TestCopyScenarioTo( const ScColumn& rDestCol ) const
    2038             : {
    2039           0 :     bool bOk = true;
    2040           0 :     ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
    2041           0 :     SCROW nStart = 0, nEnd = 0;
    2042           0 :     const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
    2043           0 :     while (pPattern && bOk)
    2044             :     {
    2045           0 :         if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
    2046           0 :             if ( rDestCol.pAttrArray->HasAttrib( nStart, nEnd, HASATTR_PROTECTED ) )
    2047           0 :                 bOk = false;
    2048             : 
    2049           0 :         pPattern = aAttrIter.Next( nStart, nEnd );
    2050             :     }
    2051           0 :     return bOk;
    2052             : }
    2053             : 
    2054             : 
    2055        1024 : void ScColumn::MarkScenarioIn( ScMarkData& rDestMark ) const
    2056             : {
    2057        1024 :     ScRange aRange( nCol, 0, nTab );
    2058             : 
    2059        1024 :     ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW );
    2060        1024 :     SCROW nStart = -1, nEnd = -1;
    2061        1024 :     const ScPatternAttr* pPattern = aAttrIter.Next( nStart, nEnd );
    2062        3086 :     while (pPattern)
    2063             :     {
    2064        1038 :         if ( ((ScMergeFlagAttr&)pPattern->GetItem( ATTR_MERGE_FLAG )).IsScenario() )
    2065             :         {
    2066          14 :             aRange.aStart.SetRow( nStart );
    2067          14 :             aRange.aEnd.SetRow( nEnd );
    2068          14 :             rDestMark.SetMultiMarkArea( aRange, true );
    2069             :         }
    2070             : 
    2071        1038 :         pPattern = aAttrIter.Next( nStart, nEnd );
    2072             :     }
    2073        1024 : }
    2074             : 
    2075             : namespace {
    2076             : 
    2077       26586 : void resetColumnPosition(sc::CellStoreType& rCells, SCCOL nCol)
    2078             : {
    2079       26586 :     sc::CellStoreType::iterator it = rCells.begin(), itEnd = rCells.end();
    2080       53194 :     for (; it != itEnd; ++it)
    2081             :     {
    2082       26608 :         if (it->type != sc::element_type_formula)
    2083       26608 :             continue;
    2084             : 
    2085           0 :         sc::formula_block::iterator itCell = sc::formula_block::begin(*it->data);
    2086           0 :         sc::formula_block::iterator itCellEnd = sc::formula_block::end(*it->data);
    2087           0 :         for (; itCell != itCellEnd; ++itCell)
    2088             :         {
    2089           0 :             ScFormulaCell& rCell = **itCell;
    2090           0 :             rCell.aPos.SetCol(nCol);
    2091             :         }
    2092             :     }
    2093       26586 : }
    2094             : 
    2095             : }
    2096             : 
    2097       13293 : void ScColumn::SwapCol(ScColumn& rCol)
    2098             : {
    2099       13293 :     maCells.swap(rCol.maCells);
    2100       13293 :     maCellTextAttrs.swap(rCol.maCellTextAttrs);
    2101             : 
    2102       13293 :     ScAttrArray* pTempAttr = rCol.pAttrArray;
    2103       13293 :     rCol.pAttrArray = pAttrArray;
    2104       13293 :     pAttrArray = pTempAttr;
    2105             : 
    2106             :     // AttrArray needs to have the right column number
    2107       13293 :     pAttrArray->SetCol(nCol);
    2108       13293 :     rCol.pAttrArray->SetCol(rCol.nCol);
    2109             : 
    2110       13293 :     std::swap(mbDirtyGroups, rCol.mbDirtyGroups);
    2111             : 
    2112             :     // Reset column positions in formula cells.
    2113       13293 :     resetColumnPosition(maCells, nCol);
    2114       13293 :     resetColumnPosition(rCol.maCells, rCol.nCol);
    2115             : 
    2116       13293 :     CellStorageModified();
    2117       13293 :     rCol.CellStorageModified();
    2118             : 
    2119       13293 : }
    2120             : 
    2121        6093 : void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
    2122             : {
    2123        6093 :     pAttrArray->MoveTo(nStartRow, nEndRow, *rCol.pAttrArray);
    2124             : 
    2125             :     // Mark the non-empty cells within the specified range, for later broadcasting.
    2126        6093 :     sc::SingleColumnSpanSet aNonEmpties;
    2127        6093 :     aNonEmpties.scan(*this, nStartRow, nEndRow);
    2128       12186 :     sc::SingleColumnSpanSet::SpansType aRanges;
    2129        6093 :     aNonEmpties.getSpans(aRanges);
    2130             : 
    2131             :     // Move the broadcasters to the destination column.
    2132        6093 :     maBroadcasters.transfer(nStartRow, nEndRow, rCol.maBroadcasters, nStartRow);
    2133        6093 :     maCells.transfer(nStartRow, nEndRow, rCol.maCells, nStartRow);
    2134        6093 :     maCellTextAttrs.transfer(nStartRow, nEndRow, rCol.maCellTextAttrs, nStartRow);
    2135             : 
    2136        6093 :     RegroupFormulaCells(nStartRow, nEndRow);
    2137        6093 :     rCol.RegroupFormulaCells(nStartRow, nEndRow);
    2138        6093 :     CellStorageModified();
    2139        6093 :     rCol.CellStorageModified();
    2140             : 
    2141             :     // Broadcast on moved ranges. Area-broadcast only.
    2142       12186 :     ScHint aHint(SC_HINT_DATACHANGED, ScAddress(nCol, 0, nTab));
    2143        6093 :     ScAddress& rPos = aHint.GetAddress();
    2144        6093 :     sc::SingleColumnSpanSet::SpansType::const_iterator itRange = aRanges.begin(), itRangeEnd = aRanges.end();
    2145        6098 :     for (; itRange != itRangeEnd; ++itRange)
    2146             :     {
    2147          10 :         for (SCROW nRow = itRange->mnRow1; nRow <= itRange->mnRow2; ++nRow)
    2148             :         {
    2149           5 :             rPos.SetRow(nRow);
    2150           5 :             pDocument->AreaBroadcast(aHint);
    2151             :         }
    2152        6093 :     }
    2153        6093 : }
    2154             : 
    2155             : namespace {
    2156             : 
    2157             : class SubTotalCellPicker
    2158             : {
    2159             :     sc::ColumnSpanSet& mrSet;
    2160             :     SCTAB mnTab;
    2161             :     SCCOL mnCol;
    2162             :     bool mbVal;
    2163             : public:
    2164           6 :     SubTotalCellPicker(sc::ColumnSpanSet& rSet, SCTAB nTab, SCCOL nCol, bool bVal) :
    2165           6 :         mrSet(rSet), mnTab(nTab), mnCol(nCol), mbVal(bVal) {}
    2166             : 
    2167           3 :     void operator() (size_t nRow, const ScFormulaCell* pCell)
    2168             :     {
    2169           3 :         if (pCell->IsSubTotal())
    2170           3 :             mrSet.set(mnTab, mnCol, nRow, mbVal);
    2171           3 :     }
    2172             : };
    2173             : 
    2174             : }
    2175             : 
    2176           6 : void ScColumn::MarkSubTotalCells( sc::ColumnSpanSet& rSet, SCROW nRow1, SCROW nRow2, bool bVal ) const
    2177             : {
    2178           6 :     SubTotalCellPicker aFunc(rSet, nTab, nCol, bVal);
    2179           6 :     sc::ParseFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc);
    2180           6 : }
    2181             : 
    2182             : namespace {
    2183             : 
    2184             : class UpdateRefOnCopy
    2185             : {
    2186             : protected:
    2187             :     ScRange maRange;
    2188             :     SCCOL mnDx;
    2189             :     SCROW mnDy;
    2190             :     SCTAB mnDz;
    2191             :     ScDocument* mpUndoDoc;
    2192             :     bool mbUpdated;
    2193             : 
    2194             : public:
    2195        5206 :     UpdateRefOnCopy(const ScRange& rRange, SCCOL nDx, SCROW nDy, SCTAB nDz, ScDocument* pUndoDoc) :
    2196        5206 :         maRange(rRange), mnDx(nDx), mnDy(nDy), mnDz(nDz), mpUndoDoc(pUndoDoc), mbUpdated(false) {}
    2197             : 
    2198        5206 :     bool isUpdated() const { return mbUpdated; }
    2199             : 
    2200        5302 :     void operator() (sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize)
    2201             :     {
    2202        5302 :         if (node.type != sc::element_type_formula)
    2203       10596 :             return;
    2204             : 
    2205           8 :         sc::formula_block::iterator it = sc::formula_block::begin(*node.data);
    2206           8 :         std::advance(it, nOffset);
    2207           8 :         sc::formula_block::iterator itEnd = it;
    2208           8 :         std::advance(itEnd, nDataSize);
    2209             : 
    2210          25 :         for (; it != itEnd; ++it)
    2211             :         {
    2212          17 :             ScFormulaCell& rCell = **it;
    2213          17 :             mbUpdated |= rCell.UpdateReference(URM_COPY, maRange, mnDx, mnDy, mnDz, mpUndoDoc);
    2214             :         }
    2215             :     }
    2216             : };
    2217             : 
    2218             : class UpdateRefOnNonCopy
    2219             : {
    2220             :     SCCOL mnCol;
    2221             :     SCROW mnTab;
    2222             :     ScRange maRange;
    2223             :     SCCOL mnDx;
    2224             :     SCROW mnDy;
    2225             :     SCTAB mnDz;
    2226             :     UpdateRefMode meMode;
    2227             :     ScDocument* mpUndoDoc;
    2228             :     bool mbUpdated;
    2229             : 
    2230             : public:
    2231       64512 :     UpdateRefOnNonCopy(
    2232             :         SCCOL nCol, SCTAB nTab, const ScRange& rRange,
    2233             :         SCCOL nDx, SCROW nDy, SCTAB nDz, UpdateRefMode eMode,
    2234             :         ScDocument* pUndoDoc) :
    2235             :         mnCol(nCol), mnTab(nTab), maRange(rRange),
    2236       64512 :         mnDx(nDx), mnDy(nDy), mnDz(nDz), meMode(eMode), mpUndoDoc(pUndoDoc), mbUpdated(false) {}
    2237             : 
    2238          34 :     void operator() (size_t nRow, ScFormulaCell* pCell)
    2239             :     {
    2240          34 :         ScAddress aUndoPos(mnCol, nRow, mnTab);
    2241          34 :         mbUpdated |= pCell->UpdateReference(meMode, maRange, mnDx, mnDy, mnDz, mpUndoDoc, &aUndoPos);
    2242          34 :     }
    2243             : 
    2244       64512 :     bool isUpdated() const { return mbUpdated; }
    2245             : };
    2246             : 
    2247             : }
    2248             : 
    2249       69718 : bool ScColumn::UpdateReference(
    2250             :     UpdateRefMode eUpdateRefMode, const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
    2251             :     ScDocument* pUndoDoc )
    2252             : {
    2253       69718 :     if (eUpdateRefMode == URM_COPY)
    2254             :     {
    2255        5206 :         UpdateRefOnCopy aHandler(rRange, nDx, nDy, nDz, pUndoDoc);
    2256        5206 :         FormulaCellsUndecided(rRange.aStart.Row(), rRange.aEnd.Row());
    2257        5206 :         sc::ProcessBlock(maCells.begin(), maCells, aHandler, rRange.aStart.Row(), rRange.aEnd.Row());
    2258        5206 :         return aHandler.isUpdated();
    2259             :     }
    2260             : 
    2261       64512 :     UpdateRefOnNonCopy aHandler(nCol, nTab, rRange, nDx, nDy, nDz, eUpdateRefMode, pUndoDoc);
    2262       64512 :     FormulaCellsUndecided(0, MAXROW);
    2263       64512 :     sc::ProcessFormula(maCells, aHandler);
    2264       64512 :     return aHandler.isUpdated();
    2265             : }
    2266             : 
    2267             : namespace {
    2268             : 
    2269             : class UpdateTransHandler
    2270             : {
    2271             :     ScRange maSource;
    2272             :     ScAddress maDest;
    2273             :     ScDocument* mpUndoDoc;
    2274             : public:
    2275           0 :     UpdateTransHandler(const ScRange& rSource, const ScAddress& rDest, ScDocument* pUndoDoc) :
    2276           0 :         maSource(rSource), maDest(rDest), mpUndoDoc(pUndoDoc) {}
    2277             : 
    2278           0 :     void operator() (size_t, ScFormulaCell* pCell)
    2279             :     {
    2280           0 :         pCell->UpdateTranspose(maSource, maDest, mpUndoDoc);
    2281           0 :     }
    2282             : };
    2283             : 
    2284             : class UpdateGrowHandler
    2285             : {
    2286             :     ScRange maArea;
    2287             :     SCCOL mnGrowX;
    2288             :     SCROW mnGrowY;
    2289             : public:
    2290           0 :     UpdateGrowHandler(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY) :
    2291           0 :         maArea(rArea), mnGrowX(nGrowX), mnGrowY(nGrowY) {}
    2292             : 
    2293           0 :     void operator() (size_t, ScFormulaCell* pCell)
    2294             :     {
    2295           0 :         pCell->UpdateGrow(maArea, mnGrowX, mnGrowY);
    2296           0 :     }
    2297             : };
    2298             : 
    2299             : class InsertTabUpdater
    2300             : {
    2301             :     sc::CellTextAttrStoreType& mrTextAttrs;
    2302             :     sc::CellTextAttrStoreType::iterator miAttrPos;
    2303             :     SCTAB mnTab;
    2304             :     SCTAB mnInsPos;
    2305             :     SCTAB mnNewSheets;
    2306             :     bool mbModified;
    2307             : 
    2308             : public:
    2309       58368 :     InsertTabUpdater(sc::CellTextAttrStoreType& rTextAttrs, SCTAB nTab, SCTAB nInsPos, SCTAB nNewSheets) :
    2310             :         mrTextAttrs(rTextAttrs),
    2311             :         miAttrPos(rTextAttrs.begin()),
    2312             :         mnTab(nTab),
    2313             :         mnInsPos(nInsPos),
    2314             :         mnNewSheets(nNewSheets),
    2315       58368 :         mbModified(false) {}
    2316             : 
    2317           6 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2318             :     {
    2319           6 :         pCell->UpdateInsertTab(mnInsPos, mnNewSheets);
    2320           6 :         mbModified = true;
    2321           6 :     }
    2322             : 
    2323           0 :     void operator() (size_t nRow, EditTextObject* pCell)
    2324             :     {
    2325           0 :         editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
    2326           0 :         aUpdater.updateTableFields(mnTab);
    2327           0 :         miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
    2328           0 :         mbModified = true;
    2329           0 :     }
    2330             : 
    2331       58368 :     bool isModified() const { return mbModified; }
    2332             : };
    2333             : 
    2334             : class DeleteTabUpdater
    2335             : {
    2336             :     sc::CellTextAttrStoreType& mrTextAttrs;
    2337             :     sc::CellTextAttrStoreType::iterator miAttrPos;
    2338             :     SCTAB mnDelPos;
    2339             :     SCTAB mnSheets;
    2340             :     SCTAB mnTab;
    2341             :     bool mbIsMove;
    2342             :     bool mbModified;
    2343             : public:
    2344      124928 :     DeleteTabUpdater(sc::CellTextAttrStoreType& rTextAttrs, SCTAB nDelPos, SCTAB nSheets, SCTAB nTab, bool bIsMove) :
    2345             :         mrTextAttrs(rTextAttrs),
    2346             :         miAttrPos(rTextAttrs.begin()),
    2347             :         mnDelPos(nDelPos),
    2348             :         mnSheets(nSheets),
    2349             :         mnTab(nTab),
    2350             :         mbIsMove(bIsMove),
    2351      124928 :         mbModified(false) {}
    2352             : 
    2353          60 :     void operator() (size_t, ScFormulaCell* pCell)
    2354             :     {
    2355          60 :         pCell->UpdateDeleteTab(mnDelPos, mbIsMove, mnSheets);
    2356          60 :         mbModified = true;
    2357          60 :     }
    2358             : 
    2359           0 :     void operator() (size_t nRow, EditTextObject* pCell)
    2360             :     {
    2361           0 :         editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
    2362           0 :         aUpdater.updateTableFields(mnTab);
    2363           0 :         miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
    2364           0 :         mbModified = true;
    2365           0 :     }
    2366             : 
    2367      124928 :     bool isModified() const { return mbModified; }
    2368             : };
    2369             : 
    2370             : class InsertAbsTabUpdater
    2371             : {
    2372             :     sc::CellTextAttrStoreType& mrTextAttrs;
    2373             :     sc::CellTextAttrStoreType::iterator miAttrPos;
    2374             :     SCTAB mnTab;
    2375             :     SCTAB mnNewPos;
    2376             :     bool mbModified;
    2377             : public:
    2378        4096 :     InsertAbsTabUpdater(sc::CellTextAttrStoreType& rTextAttrs, SCTAB nTab, SCTAB nNewPos) :
    2379             :         mrTextAttrs(rTextAttrs),
    2380             :         miAttrPos(rTextAttrs.begin()),
    2381             :         mnTab(nTab),
    2382             :         mnNewPos(nNewPos),
    2383        4096 :         mbModified(false) {}
    2384             : 
    2385           0 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2386             :     {
    2387           0 :         pCell->UpdateInsertTabAbs(mnNewPos);
    2388           0 :         mbModified = true;
    2389           0 :     }
    2390             : 
    2391           0 :     void operator() (size_t nRow, EditTextObject* pCell)
    2392             :     {
    2393           0 :         editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
    2394           0 :         aUpdater.updateTableFields(mnTab);
    2395           0 :         miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
    2396           0 :         mbModified = true;
    2397           0 :     }
    2398             : 
    2399        4096 :     bool isModified() const { return mbModified; }
    2400             : };
    2401             : 
    2402             : class MoveTabUpdater
    2403             : {
    2404             :     sc::CellTextAttrStoreType& mrTextAttrs;
    2405             :     sc::CellTextAttrStoreType::iterator miAttrPos;
    2406             :     SCTAB mnTab;
    2407             :     SCTAB mnOldPos;
    2408             :     SCTAB mnNewPos;
    2409             :     bool mbModified;
    2410             : public:
    2411       10240 :     MoveTabUpdater(sc::CellTextAttrStoreType& rTextAttrs, SCTAB nTab, SCTAB nOldPos, SCTAB nNewPos) :
    2412             :         mrTextAttrs(rTextAttrs),
    2413             :         miAttrPos(rTextAttrs.begin()),
    2414             :         mnTab(nTab),
    2415             :         mnOldPos(nOldPos),
    2416             :         mnNewPos(nNewPos),
    2417       10240 :         mbModified(false) {}
    2418             : 
    2419           0 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2420             :     {
    2421           0 :         pCell->UpdateMoveTab(mnOldPos, mnNewPos, mnTab);
    2422           0 :         mbModified = true;
    2423           0 :     }
    2424             : 
    2425           0 :     void operator() (size_t nRow, EditTextObject* pCell)
    2426             :     {
    2427           0 :         editeng::FieldUpdater aUpdater = pCell->GetFieldUpdater();
    2428           0 :         aUpdater.updateTableFields(mnTab);
    2429           0 :         miAttrPos = mrTextAttrs.set(miAttrPos, nRow, sc::CellTextAttr());
    2430           0 :         mbModified = true;
    2431           0 :     }
    2432             : 
    2433       10240 :     bool isModified() const { return mbModified; }
    2434             : };
    2435             : 
    2436             : class UpdateCompileHandler
    2437             : {
    2438             :     bool mbForceIfNameInUse:1;
    2439             : public:
    2440      185344 :     UpdateCompileHandler(bool bForceIfNameInUse) :
    2441      185344 :         mbForceIfNameInUse(bForceIfNameInUse) {}
    2442             : 
    2443          58 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2444             :     {
    2445          58 :         pCell->UpdateCompile(mbForceIfNameInUse);
    2446          58 :     }
    2447             : };
    2448             : 
    2449             : class TabNoSetter
    2450             : {
    2451             :     SCTAB mnTab;
    2452             : public:
    2453        3072 :     TabNoSetter(SCTAB nTab) : mnTab(nTab) {}
    2454             : 
    2455           5 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2456             :     {
    2457           5 :         pCell->aPos.SetTab(mnTab);
    2458           5 :     }
    2459             : };
    2460             : 
    2461             : class UsedRangeNameFinder
    2462             : {
    2463             :     std::set<sal_uInt16>& mrIndexes;
    2464             : public:
    2465           7 :     UsedRangeNameFinder(std::set<sal_uInt16>& rIndexes) : mrIndexes(rIndexes) {}
    2466             : 
    2467           1 :     void operator() (size_t /*nRow*/, const ScFormulaCell* pCell)
    2468             :     {
    2469           1 :         pCell->FindRangeNamesInUse(mrIndexes);
    2470           1 :     }
    2471             : };
    2472             : 
    2473             : struct SetDirtyVarHandler
    2474             : {
    2475         590 :     void operator() (size_t /*nRow*/, ScFormulaCell* p)
    2476             :     {
    2477         590 :         p->SetDirtyVar();
    2478         590 :     }
    2479             : };
    2480             : 
    2481             : class SetDirtyHandler
    2482             : {
    2483             :     ScDocument& mrDoc;
    2484             : public:
    2485      412672 :     SetDirtyHandler(ScDocument& rDoc) : mrDoc(rDoc) {}
    2486             : 
    2487          72 :     void operator() (size_t /*nRow*/, ScFormulaCell* p)
    2488             :     {
    2489          72 :         p->SetDirtyVar();
    2490          72 :         if (!mrDoc.IsInFormulaTree(p))
    2491          57 :             mrDoc.PutInFormulaTree(p);
    2492          72 :     }
    2493             : };
    2494             : 
    2495        3333 : class SetDirtyOnRangeHandler
    2496             : {
    2497             :     sc::SingleColumnSpanSet maValueRanges;
    2498             :     ScColumn& mrColumn;
    2499             : public:
    2500        3333 :     SetDirtyOnRangeHandler(ScColumn& rColumn) : mrColumn(rColumn) {}
    2501             : 
    2502          36 :     void operator() (size_t /*nRow*/, ScFormulaCell* p)
    2503             :     {
    2504          36 :         p->SetDirty();
    2505          36 :     }
    2506             : 
    2507        3452 :     void operator() (mdds::mtv::element_t type, size_t nTopRow, size_t nDataSize)
    2508             :     {
    2509        3452 :         if (type == sc::element_type_empty)
    2510             :             // Ignore empty blocks.
    2511        6567 :             return;
    2512             : 
    2513             :         // Non-formula cells.
    2514         337 :         SCROW nRow1 = nTopRow;
    2515         337 :         SCROW nRow2 = nTopRow + nDataSize - 1;
    2516         337 :         maValueRanges.set(nRow1, nRow2, true);
    2517             :     }
    2518             : 
    2519        3333 :     void broadcast()
    2520             :     {
    2521        3333 :         std::vector<SCROW> aRows;
    2522        3333 :         maValueRanges.getRows(aRows);
    2523        3333 :         mrColumn.BroadcastCells(aRows);
    2524        3333 :     }
    2525             : };
    2526             : 
    2527          32 : class SetTableOpDirtyOnRangeHandler
    2528             : {
    2529             :     sc::SingleColumnSpanSet maValueRanges;
    2530             :     ScColumn& mrColumn;
    2531             : public:
    2532          32 :     SetTableOpDirtyOnRangeHandler(ScColumn& rColumn) : mrColumn(rColumn) {}
    2533             : 
    2534           0 :     void operator() (size_t /*nRow*/, ScFormulaCell* p)
    2535             :     {
    2536           0 :         p->SetTableOpDirty();
    2537           0 :     }
    2538             : 
    2539          32 :     void operator() (mdds::mtv::element_t type, size_t nTopRow, size_t nDataSize)
    2540             :     {
    2541          32 :         if (type == sc::element_type_empty)
    2542             :             // Ignore empty blocks.
    2543          64 :             return;
    2544             : 
    2545             :         // Non-formula cells.
    2546           0 :         SCROW nRow1 = nTopRow;
    2547           0 :         SCROW nRow2 = nTopRow + nDataSize - 1;
    2548           0 :         maValueRanges.set(nRow1, nRow2, true);
    2549             :     }
    2550             : 
    2551          32 :     void broadcast()
    2552             :     {
    2553          32 :         std::vector<SCROW> aRows;
    2554          32 :         maValueRanges.getRows(aRows);
    2555          32 :         mrColumn.BroadcastCells(aRows);
    2556          32 :     }
    2557             : };
    2558             : 
    2559             : struct SetDirtyAfterLoadHandler
    2560             : {
    2561        2473 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2562             :     {
    2563             : #if 1
    2564             :         // Simply set dirty and append to FormulaTree, without broadcasting,
    2565             :         // which is a magnitude faster. This is used to calculate the entire
    2566             :         // document, e.g. when loading alien file formats.
    2567        2473 :         pCell->SetDirtyAfterLoad();
    2568             : #else
    2569             : /* This was used with the binary file format that stored results, where only
    2570             :  * newly compiled and volatile functions and their dependents had to be
    2571             :  * recalculated, which was faster then. Since that was moved to 'binfilter' to
    2572             :  * convert to an XML file this isn't needed anymore, and not used for other
    2573             :  * file formats. Kept for reference in case mechanism needs to be reactivated
    2574             :  * for some file formats, we'd have to introduce a controlling parameter to
    2575             :  * this method here then.
    2576             : */
    2577             : 
    2578             :         // If the cell was alsready dirty because of CalcAfterLoad,
    2579             :         // FormulaTracking has to take place.
    2580             :         if (pCell->GetDirty())
    2581             :             pCell->SetDirty();
    2582             : #endif
    2583        2473 :     }
    2584             : };
    2585             : 
    2586             : struct SetRelNameDirtyHandler
    2587             : {
    2588          29 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2589             :     {
    2590          29 :         if (pCell->HasRelNameReference())
    2591           0 :             pCell->SetDirty();
    2592          29 :     }
    2593             : };
    2594             : 
    2595             : struct CalcAllHandler
    2596             : {
    2597         590 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2598             :     {
    2599             : #if OSL_DEBUG_LEVEL > 1
    2600             :         // after F9 ctrl-F9: check the calculation for each FormulaTree
    2601             :         double nOldVal, nNewVal;
    2602             :         nOldVal = pCell->GetValue();
    2603             : #endif
    2604         590 :         pCell->Interpret();
    2605             : #if OSL_DEBUG_LEVEL > 1
    2606             :         if (pCell->GetCode()->IsRecalcModeNormal())
    2607             :             nNewVal = pCell->GetValue();
    2608             :         else
    2609             :             nNewVal = nOldVal;  // random(), jetzt() etc.
    2610             : 
    2611             :         OSL_ENSURE(nOldVal == nNewVal, "CalcAll: nOldVal != nNewVal");
    2612             : #endif
    2613         590 :     }
    2614             : };
    2615             : 
    2616             : struct CompileAllHandler
    2617             : {
    2618           6 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2619             :     {
    2620             :         // for unconditional compilation
    2621             :         // bCompile=true and pCode->nError=0
    2622           6 :         pCell->GetCode()->SetCodeError(0);
    2623           6 :         pCell->SetCompile(true);
    2624           6 :         pCell->CompileTokenArray();
    2625           6 :     }
    2626             : };
    2627             : 
    2628             : class CompileXMLHandler
    2629             : {
    2630             :     ScProgress& mrProgress;
    2631             :     const ScColumn& mrCol;
    2632             : public:
    2633      172032 :     CompileXMLHandler(ScProgress& rProgress, const ScColumn& rCol) :
    2634             :         mrProgress(rProgress),
    2635      172032 :         mrCol(rCol) {}
    2636             : 
    2637         448 :     void operator() (size_t nRow, ScFormulaCell* pCell)
    2638             :     {
    2639         448 :         sal_uInt32 nFormat = mrCol.GetNumberFormat(nRow);
    2640         448 :         if( (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) != 0)
    2641         145 :             pCell->SetNeedNumberFormat(false);
    2642             :         else
    2643         303 :             pCell->SetDirty(true);
    2644             : 
    2645         448 :         pCell->CompileXML(mrProgress);
    2646         448 :     }
    2647             : };
    2648             : 
    2649             : class CompileErrorCellsHandler
    2650             : {
    2651             :     sal_uInt16 mnErrCode;
    2652             :     FormulaGrammar::Grammar meGram;
    2653             :     bool mbCompiled;
    2654             : public:
    2655           0 :     CompileErrorCellsHandler(sal_uInt16 nErrCode, FormulaGrammar::Grammar eGram) :
    2656           0 :         mnErrCode(nErrCode), meGram(eGram), mbCompiled(false) {}
    2657             : 
    2658           0 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2659             :     {
    2660           0 :         sal_uInt16 nCurError = pCell->GetRawError();
    2661           0 :         if (!nCurError)
    2662             :             // It's not an error cell. Skip it.
    2663           0 :             return;
    2664             : 
    2665           0 :         if (mnErrCode && nCurError != mnErrCode)
    2666             :             // Error code is specified, and it doesn't match. Skip it.
    2667           0 :             return;
    2668             : 
    2669           0 :         pCell->GetCode()->SetCodeError(0);
    2670           0 :         OUStringBuffer aBuf;
    2671           0 :         pCell->GetFormula(aBuf, meGram);
    2672           0 :         pCell->Compile(aBuf.makeStringAndClear(), false, meGram);
    2673             : 
    2674           0 :         mbCompiled = true;
    2675             :     }
    2676             : 
    2677           0 :     bool isCompiled() const { return mbCompiled; }
    2678             : };
    2679             : 
    2680             : struct CalcAfterLoadHandler
    2681             : {
    2682        2473 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2683             :     {
    2684        2473 :         pCell->CalcAfterLoad();
    2685        2473 :     }
    2686             : };
    2687             : 
    2688             : struct ResetChangedHandler
    2689             : {
    2690         268 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
    2691             :     {
    2692         268 :         pCell->SetChanged(false);
    2693         268 :     }
    2694             : };
    2695             : 
    2696             : /**
    2697             :  * Ambiguous script type counts as edit cell.
    2698             :  */
    2699             : class FindEditCellsHandler
    2700             : {
    2701             :     ScColumn& mrColumn;
    2702             :     sc::CellTextAttrStoreType::iterator miAttrPos;
    2703             : 
    2704             : public:
    2705      751402 :     FindEditCellsHandler(ScColumn& rColumn, sc::CellTextAttrStoreType& rAttrs) :
    2706      751402 :         mrColumn(rColumn), miAttrPos(rAttrs.begin()) {}
    2707             : 
    2708         121 :     bool operator() (size_t, const EditTextObject*)
    2709             :     {
    2710         121 :         return true;
    2711             :     }
    2712             : 
    2713         216 :     bool operator() (size_t nRow, const ScFormulaCell* p)
    2714             :     {
    2715         216 :         sal_uInt8 nScriptType = mrColumn.GetRangeScriptType(miAttrPos, nRow, nRow);
    2716         216 :         if (IsAmbiguousScriptNonZero(nScriptType))
    2717           0 :             return true;
    2718             : 
    2719         216 :         return const_cast<ScFormulaCell*>(p)->IsMultilineResult();
    2720             :     }
    2721             : 
    2722      751958 :     std::pair<size_t,bool> operator() (mdds::mtv::element_t type, size_t nTopRow, size_t nDataSize)
    2723             :     {
    2724             :         typedef std::pair<size_t,bool> RetType;
    2725             : 
    2726      751958 :         if (type == sc::element_type_empty)
    2727      749315 :             return RetType(0, false);
    2728             : 
    2729       32126 :         for (size_t i = 0; i < nDataSize; ++i)
    2730             :         {
    2731       29483 :             SCROW nRow = nTopRow + i;
    2732       29483 :             sal_uInt8 nScriptType = mrColumn.GetRangeScriptType(miAttrPos, nRow, nRow);
    2733       29483 :             if (IsAmbiguousScriptNonZero(nScriptType))
    2734             :                 // Return the offset from the first row.
    2735           0 :                 return RetType(i, true);
    2736             :         }
    2737             : 
    2738        2643 :         return RetType(0, false);
    2739             :     }
    2740             : };
    2741             : 
    2742             : }
    2743             : 
    2744           0 : void ScColumn::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
    2745             :                                     ScDocument* pUndoDoc )
    2746             : {
    2747           0 :     UpdateTransHandler aFunc(rSource, rDest, pUndoDoc);
    2748           0 :     sc::ProcessFormula(maCells, aFunc);
    2749           0 :     RegroupFormulaCells();
    2750           0 : }
    2751             : 
    2752             : 
    2753           0 : void ScColumn::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
    2754             : {
    2755           0 :     UpdateGrowHandler aFunc(rArea, nGrowX, nGrowY);
    2756           0 :     sc::ProcessFormula(maCells, aFunc);
    2757           0 :     RegroupFormulaCells();
    2758           0 : }
    2759             : 
    2760             : 
    2761       58368 : void ScColumn::UpdateInsertTab(SCTAB nInsPos, SCTAB nNewSheets)
    2762             : {
    2763       58368 :     if (nTab >= nInsPos)
    2764             :     {
    2765       50176 :         nTab += nNewSheets;
    2766       50176 :         pAttrArray->SetTab(nTab);
    2767             :     }
    2768             : 
    2769       58368 :     UpdateInsertTabOnlyCells(nInsPos, nNewSheets);
    2770       58368 : }
    2771             : 
    2772       58368 : void ScColumn::UpdateInsertTabOnlyCells(SCTAB nInsPos, SCTAB nNewSheets)
    2773             : {
    2774       58368 :     InsertTabUpdater aFunc(maCellTextAttrs, nTab, nInsPos, nNewSheets);
    2775       58368 :     sc::ProcessFormulaEditText(maCells, aFunc);
    2776       58368 :     if (aFunc.isModified())
    2777             :     {
    2778           3 :         RegroupFormulaCells();
    2779           3 :         CellStorageModified();
    2780             :     }
    2781       58368 : }
    2782             : 
    2783      124928 : void ScColumn::UpdateDeleteTab(SCTAB nDelPos, bool bIsMove, ScColumn* /*pRefUndo*/, SCTAB nSheets)
    2784             : {
    2785      124928 :     if (nTab > nDelPos)
    2786             :     {
    2787       33792 :         nTab -= nSheets;
    2788       33792 :         pAttrArray->SetTab(nTab);
    2789             :     }
    2790             : 
    2791      124928 :     DeleteTabUpdater aFunc(maCellTextAttrs, nDelPos, nSheets, nTab, bIsMove);
    2792      124928 :     sc::ProcessFormulaEditText(maCells, aFunc);
    2793      124928 :     if (aFunc.isModified())
    2794             :     {
    2795          23 :         RegroupFormulaCells();
    2796          23 :         CellStorageModified();
    2797             :     }
    2798      124928 : }
    2799             : 
    2800        4096 : void ScColumn::UpdateInsertTabAbs(SCTAB nNewPos)
    2801             : {
    2802        4096 :     InsertAbsTabUpdater aFunc(maCellTextAttrs, nTab, nNewPos);
    2803        4096 :     sc::ProcessFormulaEditText(maCells, aFunc);
    2804        4096 :     if (aFunc.isModified())
    2805             :     {
    2806           0 :         RegroupFormulaCells();
    2807           0 :         CellStorageModified();
    2808             :     }
    2809        4096 : }
    2810             : 
    2811       10240 : void ScColumn::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo )
    2812             : {
    2813       10240 :     nTab = nTabNo;
    2814       10240 :     pAttrArray->SetTab( nTabNo );
    2815             : 
    2816       10240 :     MoveTabUpdater aFunc(maCellTextAttrs, nTab, nOldPos, nNewPos);
    2817       10240 :     sc::ProcessFormulaEditText(maCells, aFunc);
    2818       10240 :     if (aFunc.isModified())
    2819             :     {
    2820           0 :         RegroupFormulaCells();
    2821           0 :         CellStorageModified();
    2822             :     }
    2823       10240 : }
    2824             : 
    2825             : 
    2826      185344 : void ScColumn::UpdateCompile( bool bForceIfNameInUse )
    2827             : {
    2828      185344 :     UpdateCompileHandler aFunc(bForceIfNameInUse);
    2829      185344 :     sc::ProcessFormula(maCells, aFunc);
    2830      185344 :     RegroupFormulaCells();
    2831      185344 : }
    2832             : 
    2833             : 
    2834        3072 : void ScColumn::SetTabNo(SCTAB nNewTab)
    2835             : {
    2836        3072 :     nTab = nNewTab;
    2837        3072 :     pAttrArray->SetTab( nNewTab );
    2838             : 
    2839        3072 :     TabNoSetter aFunc(nTab);
    2840        3072 :     sc::ProcessFormula(maCells, aFunc);
    2841        3072 : }
    2842             : 
    2843           7 : void ScColumn::FindRangeNamesInUse(SCROW nRow1, SCROW nRow2, std::set<sal_uInt16>& rIndexes) const
    2844             : {
    2845           7 :     UsedRangeNameFinder aFunc(rIndexes);
    2846           7 :     sc::ParseFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc);
    2847           7 : }
    2848             : 
    2849      190464 : void ScColumn::SetDirtyVar()
    2850             : {
    2851             :     SetDirtyVarHandler aFunc;
    2852      190464 :     sc::ProcessFormula(maCells, aFunc);
    2853      190464 : }
    2854             : 
    2855           0 : bool ScColumn::IsFormulaDirty( SCROW nRow ) const
    2856             : {
    2857           0 :     if (!ValidRow(nRow))
    2858           0 :         return false;
    2859             : 
    2860           0 :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(nRow);
    2861           0 :     sc::CellStoreType::const_iterator it = aPos.first;
    2862           0 :     if (it->type != sc::element_type_formula)
    2863             :         // This is not a formula cell block.
    2864           0 :         return false;
    2865             : 
    2866           0 :     const ScFormulaCell* p = sc::formula_block::at(*it->data, aPos.second);
    2867           0 :     return p->GetDirty();
    2868             : }
    2869             : 
    2870      412672 : void ScColumn::SetDirty()
    2871             : {
    2872             :     // is only done documentwide, no FormulaTracking
    2873      412672 :     sc::AutoCalcSwitch aSwitch(*pDocument, false);
    2874      412672 :     SetDirtyHandler aFunc(*pDocument);
    2875      412672 :     sc::ProcessFormula(maCells, aFunc);
    2876      412672 : }
    2877             : 
    2878        3333 : void ScColumn::SetDirty( SCROW nRow1, SCROW nRow2 )
    2879             : {
    2880             :     // broadcasts everything within the range, with FormulaTracking
    2881        3333 :     sc::AutoCalcSwitch aSwitch(*pDocument, false);
    2882             : 
    2883        6666 :     SetDirtyOnRangeHandler aHdl(*this);
    2884        3333 :     sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aHdl, aHdl);
    2885        6666 :     aHdl.broadcast();
    2886        3333 : }
    2887             : 
    2888          32 : void ScColumn::SetTableOpDirty( const ScRange& rRange )
    2889             : {
    2890          32 :     sc::AutoCalcSwitch aSwitch(*pDocument, false);
    2891             : 
    2892          32 :     SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
    2893          64 :     SetTableOpDirtyOnRangeHandler aHdl(*this);
    2894          32 :     sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aHdl, aHdl);
    2895          64 :     aHdl.broadcast();
    2896          32 : }
    2897             : 
    2898      166912 : void ScColumn::SetDirtyAfterLoad()
    2899             : {
    2900      166912 :     sc::AutoCalcSwitch aSwitch(*pDocument, false);
    2901             :     SetDirtyAfterLoadHandler aFunc;
    2902      166912 :     sc::ProcessFormula(maCells, aFunc);
    2903      166912 : }
    2904             : 
    2905       60416 : void ScColumn::SetRelNameDirty()
    2906             : {
    2907       60416 :     sc::AutoCalcSwitch aSwitch(*pDocument, false);
    2908             :     SetRelNameDirtyHandler aFunc;
    2909       60416 :     sc::ProcessFormula(maCells, aFunc);
    2910       60416 : }
    2911             : 
    2912      190464 : void ScColumn::CalcAll()
    2913             : {
    2914             :     CalcAllHandler aFunc;
    2915      190464 :     sc::ProcessFormula(maCells, aFunc);
    2916      190464 : }
    2917             : 
    2918        3072 : void ScColumn::CompileAll()
    2919             : {
    2920             :     CompileAllHandler aFunc;
    2921        3072 :     sc::ProcessFormula(maCells, aFunc);
    2922        3072 : }
    2923             : 
    2924      172032 : void ScColumn::CompileXML( ScProgress& rProgress )
    2925             : {
    2926      172032 :     CompileXMLHandler aFunc(rProgress, *this);
    2927      172032 :     sc::ProcessFormula(maCells, aFunc);
    2928      172032 :     RegroupFormulaCells();
    2929      172032 : }
    2930             : 
    2931           0 : bool ScColumn::CompileErrorCells(sal_uInt16 nErrCode)
    2932             : {
    2933           0 :     CompileErrorCellsHandler aHdl(nErrCode, pDocument->GetGrammar());
    2934           0 :     sc::ProcessFormula(maCells, aHdl);
    2935           0 :     if (aHdl.isCompiled())
    2936             :         // TODO: Probably more efficient to do this individually rather than the whole column.
    2937           0 :         RegroupFormulaCells();
    2938             : 
    2939           0 :     return aHdl.isCompiled();
    2940             : }
    2941             : 
    2942      166912 : void ScColumn::CalcAfterLoad()
    2943             : {
    2944             :     CalcAfterLoadHandler aFunc;
    2945      166912 :     sc::ProcessFormula(maCells, aFunc);
    2946      166912 : }
    2947             : 
    2948       17080 : void ScColumn::ResetChanged( SCROW nStartRow, SCROW nEndRow )
    2949             : {
    2950             :     ResetChangedHandler aFunc;
    2951       17080 :     sc::ProcessFormula(maCells.begin(), maCells, nStartRow, nEndRow, aFunc);
    2952       17080 : }
    2953             : 
    2954      751402 : bool ScColumn::HasEditCells(SCROW nStartRow, SCROW nEndRow, SCROW& rFirst)
    2955             : {
    2956             :     //  used in GetOptimalHeight - ambiguous script type counts as edit cell
    2957             : 
    2958      751402 :     FindEditCellsHandler aFunc(*this, maCellTextAttrs);
    2959             :     std::pair<sc::CellStoreType::const_iterator,size_t> aPos =
    2960      751402 :         sc::FindFormulaEditText(maCells, nStartRow, nEndRow, aFunc);
    2961             : 
    2962      751402 :     if (aPos.first == maCells.end())
    2963      751281 :         return false;
    2964             : 
    2965         121 :     rFirst = aPos.first->position + aPos.second;
    2966         121 :     return true;
    2967             : }
    2968             : 
    2969             : 
    2970           0 : SCsROW ScColumn::SearchStyle(
    2971             :     SCsROW nRow, const ScStyleSheet* pSearchStyle, bool bUp, bool bInSelection,
    2972             :     const ScMarkData& rMark) const
    2973             : {
    2974           0 :     if (bInSelection)
    2975             :     {
    2976           0 :         if (rMark.IsMultiMarked())
    2977           0 :             return pAttrArray->SearchStyle(nRow, pSearchStyle, bUp, rMark.GetArray()+nCol);
    2978             :         else
    2979           0 :             return -1;
    2980             :     }
    2981             :     else
    2982           0 :         return pAttrArray->SearchStyle( nRow, pSearchStyle, bUp, NULL );
    2983             : }
    2984             : 
    2985             : 
    2986           0 : bool ScColumn::SearchStyleRange(
    2987             :     SCsROW& rRow, SCsROW& rEndRow, const ScStyleSheet* pSearchStyle, bool bUp,
    2988             :     bool bInSelection, const ScMarkData& rMark) const
    2989             : {
    2990           0 :     if (bInSelection)
    2991             :     {
    2992           0 :         if (rMark.IsMultiMarked())
    2993             :             return pAttrArray->SearchStyleRange(
    2994           0 :                 rRow, rEndRow, pSearchStyle, bUp, rMark.GetArray() + nCol);
    2995             :         else
    2996           0 :             return false;
    2997             :     }
    2998             :     else
    2999           0 :         return pAttrArray->SearchStyleRange( rRow, rEndRow, pSearchStyle, bUp, NULL );
    3000          93 : }
    3001             : 
    3002             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10