LCOV - code coverage report
Current view: top level - sc/source/core/data - column4.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 448 557 80.4 %
Date: 2014-11-03 Functions: 56 62 90.3 %
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             : 
      10             : #include <column.hxx>
      11             : #include <clipparam.hxx>
      12             : #include <cellvalue.hxx>
      13             : #include <attarray.hxx>
      14             : #include <document.hxx>
      15             : #include <cellvalues.hxx>
      16             : #include <columnspanset.hxx>
      17             : #include <listenercontext.hxx>
      18             : #include <tokenstringcontext.hxx>
      19             : #include <mtvcellfunc.hxx>
      20             : #include <clipcontext.hxx>
      21             : #include <attrib.hxx>
      22             : #include <patattr.hxx>
      23             : #include <docpool.hxx>
      24             : #include <conditio.hxx>
      25             : #include <formulagroup.hxx>
      26             : #include <tokenarray.hxx>
      27             : #include <globalnames.hxx>
      28             : #include <scitems.hxx>
      29             : #include <cellform.hxx>
      30             : #include <sharedformula.hxx>
      31             : 
      32             : #include <svl/sharedstringpool.hxx>
      33             : 
      34             : #include <vector>
      35             : #include <cassert>
      36             : 
      37             : #include <boost/shared_ptr.hpp>
      38             : 
      39           6 : bool ScColumn::IsMerged( SCROW nRow ) const
      40             : {
      41           6 :     return pAttrArray->IsMerged(nRow);
      42             : }
      43             : 
      44           8 : void ScColumn::DeleteBeforeCopyFromClip( sc::CopyFromClipContext& rCxt, const ScColumn& rClipCol )
      45             : {
      46           8 :     sc::CopyFromClipContext::Range aRange = rCxt.getDestRange();
      47           8 :     if (!ValidRow(aRange.mnRow1) || !ValidRow(aRange.mnRow2))
      48           2 :         return;
      49             : 
      50           8 :     ScRange aClipRange = rCxt.getClipDoc()->GetClipParam().getWholeRange();
      51           8 :     SCROW nClipRow1 = aClipRange.aStart.Row();
      52           8 :     SCROW nClipRow2 = aClipRange.aEnd.Row();
      53           8 :     SCROW nClipRowLen = nClipRow2 - nClipRow1 + 1;
      54             : 
      55             :     // Check for non-empty cell ranges in the clip column.
      56           8 :     sc::SingleColumnSpanSet aSpanSet;
      57           8 :     aSpanSet.scan(rClipCol, nClipRow1, nClipRow2);
      58          14 :     sc::SingleColumnSpanSet::SpansType aSpans;
      59           8 :     aSpanSet.getSpans(aSpans);
      60             : 
      61           8 :     if (aSpans.empty())
      62             :         // All cells in the range in the clip are empty.  Nothing to delete.
      63           2 :         return;
      64             : 
      65             :     // Translate the clip column spans into the destination column, and repeat as needed.
      66          12 :     std::vector<sc::RowSpan> aDestSpans;
      67           6 :     SCROW nDestOffset = aRange.mnRow1 - nClipRow1;
      68           6 :     bool bContinue = true;
      69          24 :     while (bContinue)
      70             :     {
      71          12 :         sc::SingleColumnSpanSet::SpansType::const_iterator it = aSpans.begin(), itEnd = aSpans.end();
      72          28 :         for (; it != itEnd && bContinue; ++it)
      73             :         {
      74          16 :             const sc::RowSpan& r = *it;
      75          16 :             SCROW nDestRow1 = r.mnRow1 + nDestOffset;
      76          16 :             SCROW nDestRow2 = r.mnRow2 + nDestOffset;
      77             : 
      78          16 :             if (nDestRow1 > aRange.mnRow2)
      79             :             {
      80             :                 // We're done.
      81           6 :                 bContinue = false;
      82           6 :                 continue;
      83             :             }
      84             : 
      85          10 :             if (nDestRow2 > aRange.mnRow2)
      86             :             {
      87             :                 // Truncate this range, and set it as the last span.
      88           0 :                 nDestRow2 = aRange.mnRow2;
      89           0 :                 bContinue = false;
      90             :             }
      91             : 
      92          10 :             aDestSpans.push_back(sc::RowSpan(nDestRow1, nDestRow2));
      93             :         }
      94             : 
      95          12 :         nDestOffset += nClipRowLen;
      96             :     }
      97             : 
      98          12 :     std::vector<SCROW> aDeletedRows;
      99           6 :     InsertDeleteFlags nDelFlag = rCxt.getDeleteFlag();
     100           6 :     sc::ColumnBlockPosition aBlockPos;
     101           6 :     InitBlockPosition(aBlockPos);
     102             : 
     103           6 :     std::vector<sc::RowSpan>::const_iterator it = aDestSpans.begin(), itEnd = aDestSpans.end();
     104          16 :     for (; it != itEnd; ++it)
     105             :     {
     106          10 :         SCROW nRow1 = it->mnRow1;
     107          10 :         SCROW nRow2 = it->mnRow2;
     108             : 
     109          10 :         if (nDelFlag & IDF_CONTENTS)
     110          10 :             DeleteCells(aBlockPos, nRow1, nRow2, nDelFlag, aDeletedRows);
     111             : 
     112          10 :         if (nDelFlag & IDF_NOTE)
     113          10 :             DeleteCellNotes(aBlockPos, nRow1, nRow2);
     114             : 
     115          10 :         if (nDelFlag & IDF_EDITATTR)
     116           0 :             RemoveEditAttribs(nRow1, nRow2);
     117             : 
     118             :         // Delete attributes just now
     119          10 :         if (nDelFlag & IDF_ATTRIB)
     120             :         {
     121          10 :             pAttrArray->DeleteArea(nRow1, nRow2);
     122             : 
     123          10 :             if (rCxt.isTableProtected())
     124             :             {
     125           0 :                 ScPatternAttr aPattern(pDocument->GetPool());
     126           0 :                 aPattern.GetItemSet().Put(ScProtectionAttr(false));
     127           0 :                 ApplyPatternArea(nRow1, nRow2, aPattern);
     128             :             }
     129             : 
     130          10 :             ScConditionalFormatList* pCondList = rCxt.getCondFormatList();
     131          10 :             if (pCondList)
     132          10 :                 pCondList->DeleteArea(nCol, nRow1, nCol, nRow2);
     133             :         }
     134           0 :         else if ((nDelFlag & IDF_HARDATTR) == IDF_HARDATTR)
     135           0 :             pAttrArray->DeleteHardAttr(nRow1, nRow2);
     136             :     }
     137             : 
     138          12 :     BroadcastCells(aDeletedRows, SC_HINT_DATACHANGED);
     139             : }
     140             : 
     141           6 : void ScColumn::CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1, SCROW nRow2 )
     142             : {
     143             :     assert(nRow1 <= nRow2);
     144             : 
     145           6 :     size_t nDestSize = nRow2 - nRow1 + 1;
     146           6 :     sc::ColumnBlockPosition* pBlockPos = rCxt.getBlockPosition(nTab, nCol);
     147           6 :     if (!pBlockPos)
     148           6 :         return;
     149             : 
     150           6 :     ScCellValue& rSrcCell = rCxt.getSingleCell();
     151             : 
     152           6 :     InsertDeleteFlags nFlags = rCxt.getInsertFlag();
     153             : 
     154           6 :     if ((nFlags & IDF_ATTRIB) != IDF_NONE)
     155             :     {
     156           6 :         if (!rCxt.isSkipAttrForEmptyCells() || rSrcCell.meType != CELLTYPE_NONE)
     157             :         {
     158           6 :             const ScPatternAttr* pAttr = rCxt.getSingleCellPattern();
     159           6 :             pAttrArray->SetPatternArea(nRow1, nRow2, pAttr, true);
     160             :         }
     161             :     }
     162             : 
     163           6 :     if ((nFlags & IDF_CONTENTS) != IDF_NONE)
     164             :     {
     165           6 :         std::vector<sc::CellTextAttr> aTextAttrs(nDestSize);
     166             : 
     167           6 :         switch (rSrcCell.meType)
     168             :         {
     169             :             case CELLTYPE_VALUE:
     170             :             {
     171           0 :                 std::vector<double> aVals(nDestSize, rSrcCell.mfValue);
     172           0 :                 pBlockPos->miCellPos =
     173           0 :                     maCells.set(pBlockPos->miCellPos, nRow1, aVals.begin(), aVals.end());
     174           0 :                 pBlockPos->miCellTextAttrPos =
     175           0 :                     maCellTextAttrs.set(pBlockPos->miCellTextAttrPos, nRow1, aTextAttrs.begin(), aTextAttrs.end());
     176           0 :                 CellStorageModified();
     177             :             }
     178           0 :             break;
     179             :             case CELLTYPE_STRING:
     180             :             {
     181             :                 // Compare the ScDocumentPool* to determine if we are copying within the
     182             :                 // same document. If not, re-intern shared strings.
     183           2 :                 svl::SharedStringPool* pSharedStringPool = (rCxt.getClipDoc()->GetPool() != pDocument->GetPool()) ?
     184           2 :                     &pDocument->GetSharedStringPool() : NULL;
     185             :                 svl::SharedString aStr = (pSharedStringPool ?
     186             :                         pSharedStringPool->intern( rSrcCell.mpString->getString()) :
     187           2 :                         *rSrcCell.mpString);
     188             : 
     189           4 :                 std::vector<svl::SharedString> aStrs(nDestSize, aStr);
     190           4 :                 pBlockPos->miCellPos =
     191           2 :                     maCells.set(pBlockPos->miCellPos, nRow1, aStrs.begin(), aStrs.end());
     192           4 :                 pBlockPos->miCellTextAttrPos =
     193           2 :                     maCellTextAttrs.set(pBlockPos->miCellTextAttrPos, nRow1, aTextAttrs.begin(), aTextAttrs.end());
     194           4 :                 CellStorageModified();
     195             :             }
     196           2 :             break;
     197             :             case CELLTYPE_EDIT:
     198             :             {
     199           0 :                 std::vector<EditTextObject*> aStrs;
     200           0 :                 aStrs.reserve(nDestSize);
     201           0 :                 for (size_t i = 0; i < nDestSize; ++i)
     202           0 :                     aStrs.push_back(rSrcCell.mpEditText->Clone());
     203             : 
     204           0 :                 pBlockPos->miCellPos =
     205           0 :                     maCells.set(pBlockPos->miCellPos, nRow1, aStrs.begin(), aStrs.end());
     206           0 :                 pBlockPos->miCellTextAttrPos =
     207           0 :                     maCellTextAttrs.set(pBlockPos->miCellTextAttrPos, nRow1, aTextAttrs.begin(), aTextAttrs.end());
     208           0 :                 CellStorageModified();
     209             :             }
     210           0 :             break;
     211             :             case CELLTYPE_FORMULA:
     212             :             {
     213           2 :                 std::vector<sc::RowSpan> aRanges;
     214           2 :                 aRanges.reserve(1);
     215           2 :                 aRanges.push_back(sc::RowSpan(nRow1, nRow2));
     216           2 :                 CloneFormulaCell(*rSrcCell.mpFormula, aRanges);
     217             :             }
     218           2 :             break;
     219             :             default:
     220             :                 ;
     221           6 :         }
     222             :     }
     223             : 
     224           6 :     const ScPostIt* pNote = rCxt.getSingleCellNote();
     225           6 :     if (pNote && (nFlags & (IDF_NOTE | IDF_ADDNOTES)) != IDF_NONE)
     226             :     {
     227             :         // Duplicate the cell note over the whole pasted range.
     228             : 
     229           0 :         ScDocument* pClipDoc = rCxt.getClipDoc();
     230           0 :         const ScAddress& rSrcPos = pClipDoc->GetClipParam().getWholeRange().aStart;
     231           0 :         std::vector<ScPostIt*> aNotes;
     232           0 :         ScAddress aDestPos(nCol, nRow1, nTab);
     233           0 :         aNotes.reserve(nDestSize);
     234           0 :         for (size_t i = 0; i < nDestSize; ++i)
     235             :         {
     236           0 :             bool bCloneCaption = (nFlags & IDF_NOCAPTIONS) == IDF_NONE;
     237           0 :             aNotes.push_back(pNote->Clone(rSrcPos, *pDocument, aDestPos, bCloneCaption));
     238           0 :             aDestPos.IncRow();
     239             :         }
     240             : 
     241           0 :         pBlockPos->miCellNotePos =
     242             :             maCellNotes.set(
     243           0 :                 pBlockPos->miCellNotePos, nRow1, aNotes.begin(), aNotes.end());
     244             :     }
     245             : }
     246             : 
     247           0 : void ScColumn::SetValues( SCROW nRow, const std::vector<double>& rVals )
     248             : {
     249           0 :     if (!ValidRow(nRow))
     250           0 :         return;
     251             : 
     252           0 :     SCROW nLastRow = nRow + rVals.size() - 1;
     253           0 :     if (nLastRow > MAXROW)
     254             :         // Out of bound. Do nothing.
     255           0 :         return;
     256             : 
     257           0 :     sc::CellStoreType::position_type aPos = maCells.position(nRow);
     258           0 :     DetachFormulaCells(aPos, rVals.size());
     259             : 
     260           0 :     maCells.set(nRow, rVals.begin(), rVals.end());
     261           0 :     std::vector<sc::CellTextAttr> aDefaults(rVals.size());
     262           0 :     maCellTextAttrs.set(nRow, aDefaults.begin(), aDefaults.end());
     263             : 
     264           0 :     CellStorageModified();
     265             : 
     266           0 :     std::vector<SCROW> aRows;
     267           0 :     aRows.reserve(rVals.size());
     268           0 :     for (SCROW i = nRow; i <= nLastRow; ++i)
     269           0 :         aRows.push_back(i);
     270             : 
     271           0 :     BroadcastCells(aRows, SC_HINT_DATACHANGED);
     272             : }
     273             : 
     274           0 : void ScColumn::TransferCellValuesTo( SCROW nRow, size_t nLen, sc::CellValues& rDest )
     275             : {
     276           0 :     if (!ValidRow(nRow))
     277           0 :         return;
     278             : 
     279           0 :     SCROW nLastRow = nRow + nLen - 1;
     280           0 :     if (nLastRow > MAXROW)
     281             :         // Out of bound. Do nothing.
     282           0 :         return;
     283             : 
     284           0 :     sc::CellStoreType::position_type aPos = maCells.position(nRow);
     285           0 :     DetachFormulaCells(aPos, nLen);
     286             : 
     287           0 :     rDest.transferFrom(*this, nRow, nLen);
     288             : 
     289           0 :     CellStorageModified();
     290             : 
     291           0 :     std::vector<SCROW> aRows;
     292           0 :     aRows.reserve(nLen);
     293           0 :     for (SCROW i = nRow; i <= nLastRow; ++i)
     294           0 :         aRows.push_back(i);
     295             : 
     296           0 :     BroadcastCells(aRows, SC_HINT_DATACHANGED);
     297             : }
     298             : 
     299           0 : void ScColumn::CopyCellValuesFrom( SCROW nRow, const sc::CellValues& rSrc )
     300             : {
     301           0 :     if (!ValidRow(nRow))
     302           0 :         return;
     303             : 
     304           0 :     SCROW nLastRow = nRow + rSrc.size() - 1;
     305           0 :     if (nLastRow > MAXROW)
     306             :         // Out of bound. Do nothing
     307           0 :         return;
     308             : 
     309           0 :     sc::CellStoreType::position_type aPos = maCells.position(nRow);
     310           0 :     DetachFormulaCells(aPos, rSrc.size());
     311             : 
     312           0 :     rSrc.copyTo(*this, nRow);
     313             : 
     314           0 :     CellStorageModified();
     315             : 
     316           0 :     std::vector<SCROW> aRows;
     317           0 :     aRows.reserve(rSrc.size());
     318           0 :     for (SCROW i = nRow; i <= nLastRow; ++i)
     319           0 :         aRows.push_back(i);
     320             : 
     321           0 :     BroadcastCells(aRows, SC_HINT_DATACHANGED);
     322             : }
     323             : 
     324             : namespace {
     325             : 
     326           6 : class ConvertFormulaToValueHandler
     327             : {
     328             :     sc::CellValues maResValues;
     329             :     bool mbModified;
     330             : 
     331             : public:
     332           6 :     ConvertFormulaToValueHandler( SCTAB, SCCOL ) :
     333           6 :         mbModified(false)
     334             :     {
     335           6 :         maResValues.reset(MAXROWCOUNT);
     336           6 :     }
     337             : 
     338          12 :     void operator() ( size_t nRow, const ScFormulaCell* pCell )
     339             :     {
     340          12 :         sc::FormulaResultValue aRes = pCell->GetResult();
     341          12 :         switch (aRes.meType)
     342             :         {
     343             :             case sc::FormulaResultValue::Value:
     344          12 :                 maResValues.setValue(nRow, aRes.mfValue);
     345          12 :             break;
     346             :             case sc::FormulaResultValue::String:
     347           0 :                 maResValues.setValue(nRow, aRes.maString);
     348           0 :             break;
     349             :             case sc::FormulaResultValue::Error:
     350             :             case sc::FormulaResultValue::Invalid:
     351             :             default:
     352           0 :                 maResValues.setValue(nRow, svl::SharedString::getEmptyString());
     353             :         }
     354             : 
     355          12 :         mbModified = true;
     356          12 :     }
     357             : 
     358           6 :     bool isModified() const { return mbModified; }
     359             : 
     360           6 :     sc::CellValues& getResValues() { return maResValues; }
     361             : };
     362             : 
     363             : }
     364             : 
     365           6 : void ScColumn::ConvertFormulaToValue(
     366             :     sc::EndListeningContext& rCxt, SCROW nRow1, SCROW nRow2, sc::TableValues* pUndo )
     367             : {
     368           6 :     if (!ValidRow(nRow1) || !ValidRow(nRow2) || nRow1 > nRow2)
     369           0 :         return;
     370             : 
     371           6 :     std::vector<SCROW> aBounds;
     372           6 :     aBounds.push_back(nRow1);
     373           6 :     if (nRow2 < MAXROW-1)
     374           6 :         aBounds.push_back(nRow2+1);
     375             : 
     376             :     // Split formula cell groups at top and bottom boundaries (if applicable).
     377           6 :     sc::SharedFormulaUtil::splitFormulaCellGroups(maCells, aBounds);
     378             : 
     379             :     // Parse all formulas within the range and store their results into temporary storage.
     380          12 :     ConvertFormulaToValueHandler aFunc(nTab, nCol);
     381           6 :     sc::ParseFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc);
     382           6 :     if (!aFunc.isModified())
     383             :         // No formula cells encountered.
     384           0 :         return;
     385             : 
     386           6 :     DetachFormulaCells(rCxt, nRow1, nRow2);
     387             : 
     388             :     // Undo storage to hold static values which will get swapped to the cell storage later.
     389          12 :     sc::CellValues aUndoCells;
     390           6 :     aFunc.getResValues().swap(aUndoCells);
     391           6 :     aUndoCells.swapNonEmpty(*this);
     392           6 :     if (pUndo)
     393          12 :         pUndo->swap(nTab, nCol, aUndoCells);
     394             : }
     395             : 
     396             : namespace {
     397             : 
     398             : class StartListeningHandler
     399             : {
     400             :     sc::StartListeningContext& mrCxt;
     401             : 
     402             : public:
     403          14 :     StartListeningHandler( sc::StartListeningContext& rCxt ) :
     404          14 :         mrCxt(rCxt) {}
     405             : 
     406          20 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
     407             :     {
     408          20 :         pCell->StartListeningTo(mrCxt);
     409          20 :     }
     410             : };
     411             : 
     412             : class EndListeningHandler
     413             : {
     414             :     sc::EndListeningContext& mrCxt;
     415             : 
     416             : public:
     417          14 :     EndListeningHandler( sc::EndListeningContext& rCxt ) :
     418          14 :         mrCxt(rCxt) {}
     419             : 
     420           8 :     void operator() (size_t /*nRow*/, ScFormulaCell* pCell)
     421             :     {
     422           8 :         pCell->EndListeningTo(mrCxt);
     423           8 :     }
     424             : };
     425             : 
     426             : }
     427             : 
     428          14 : void ScColumn::SwapNonEmpty(
     429             :     sc::TableValues& rValues, sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt )
     430             : {
     431          14 :     const ScRange& rRange = rValues.getRange();
     432          14 :     std::vector<SCROW> aBounds;
     433          14 :     aBounds.push_back(rRange.aStart.Row());
     434          14 :     if (rRange.aEnd.Row() < MAXROW-1)
     435          14 :         aBounds.push_back(rRange.aEnd.Row()+1);
     436             : 
     437             :     // Split formula cell groups at top and bottom boundaries (if applicable).
     438          14 :     sc::SharedFormulaUtil::splitFormulaCellGroups(maCells, aBounds);
     439          28 :     std::vector<sc::CellValueSpan> aSpans = rValues.getNonEmptySpans(nTab, nCol);
     440             : 
     441             :     // Detach formula cells within the spans (if any).
     442          14 :     EndListeningHandler aEndLisFunc(rEndCxt);
     443          14 :     std::vector<sc::CellValueSpan>::const_iterator it = aSpans.begin(), itEnd = aSpans.end();
     444          14 :     sc::CellStoreType::iterator itPos = maCells.begin();
     445          30 :     for (; it != itEnd; ++it)
     446             :     {
     447          16 :         SCROW nRow1 = it->mnRow1;
     448          16 :         SCROW nRow2 = it->mnRow2;
     449          16 :         itPos = sc::ProcessFormula(itPos, maCells, nRow1, nRow2, aEndLisFunc);
     450             :     }
     451             : 
     452          14 :     rValues.swapNonEmpty(nTab, nCol, *this);
     453          14 :     RegroupFormulaCells();
     454             : 
     455             :     // Attach formula cells within the spans (if any).
     456          14 :     StartListeningHandler aStartLisFunc(rStartCxt);
     457          14 :     it = aSpans.begin();
     458          14 :     itPos = maCells.begin();
     459          30 :     for (; it != itEnd; ++it)
     460             :     {
     461          16 :         SCROW nRow1 = it->mnRow1;
     462          16 :         SCROW nRow2 = it->mnRow2;
     463          16 :         itPos = sc::ProcessFormula(itPos, maCells, nRow1, nRow2, aStartLisFunc);
     464             :     }
     465             : 
     466          28 :     CellStorageModified();
     467          14 : }
     468             : 
     469           2 : void ScColumn::DeleteRanges( const std::vector<sc::RowSpan>& rRanges, InsertDeleteFlags nDelFlag, bool bBroadcast )
     470             : {
     471           2 :     std::vector<sc::RowSpan>::const_iterator itSpan = rRanges.begin(), itSpanEnd = rRanges.end();
     472           4 :     for (; itSpan != itSpanEnd; ++itSpan)
     473           2 :         DeleteArea(itSpan->mnRow1, itSpan->mnRow2, nDelFlag, bBroadcast);
     474           2 : }
     475             : 
     476           4 : void ScColumn::CloneFormulaCell( const ScFormulaCell& rSrc, const std::vector<sc::RowSpan>& rRanges )
     477             : {
     478           4 :     sc::CellStoreType::iterator itPos = maCells.begin();
     479           4 :     sc::CellTextAttrStoreType::iterator itAttrPos = maCellTextAttrs.begin();
     480           4 :     sc::StartListeningContext aCxt(*pDocument);
     481             : 
     482           8 :     std::vector<ScFormulaCell*> aFormulas;
     483           4 :     std::vector<sc::RowSpan>::const_iterator itSpan = rRanges.begin(), itSpanEnd = rRanges.end();
     484           8 :     for (; itSpan != itSpanEnd; ++itSpan)
     485             :     {
     486           4 :         SCROW nRow1 = itSpan->mnRow1, nRow2 = itSpan->mnRow2;
     487           4 :         size_t nLen = nRow2 - nRow1 + 1;
     488             :         assert(nLen > 0);
     489           4 :         aFormulas.clear();
     490           4 :         aFormulas.reserve(nLen);
     491             : 
     492           4 :         ScAddress aPos(nCol, nRow1, nTab);
     493             : 
     494           4 :         if (nLen == 1)
     495             :         {
     496             :             // Single, ungrouped formula cell.
     497           2 :             ScFormulaCell* pCell = new ScFormulaCell(rSrc, *pDocument, aPos);
     498           2 :             pCell->StartListeningTo(aCxt);
     499           2 :             pCell->SetDirty();
     500           2 :             aFormulas.push_back(pCell);
     501             :         }
     502             :         else
     503             :         {
     504             :             // Create a group of formula cells.
     505           2 :             ScFormulaCellGroupRef xGroup(new ScFormulaCellGroup);
     506           2 :             xGroup->setCode(*rSrc.GetCode());
     507           2 :             xGroup->compileCode(*pDocument, aPos, pDocument->GetGrammar());
     508          22 :             for (size_t i = 0; i < nLen; ++i, aPos.IncRow())
     509             :             {
     510          20 :                 ScFormulaCell* pCell = new ScFormulaCell(pDocument, aPos, xGroup);
     511          20 :                 if (i == 0)
     512             :                 {
     513           2 :                     xGroup->mpTopCell = pCell;
     514           2 :                     xGroup->mnLength = nLen;
     515             :                 }
     516          20 :                 pCell->StartListeningTo(aCxt);
     517          20 :                 pCell->SetDirty();
     518          20 :                 aFormulas.push_back(pCell);
     519           2 :             }
     520             :         }
     521             : 
     522           4 :         itPos = maCells.set(itPos, nRow1, aFormulas.begin(), aFormulas.end());
     523             : 
     524             :         // Join the top and bottom of the pasted formula cells as needed.
     525           4 :         sc::CellStoreType::position_type aPosObj = maCells.position(itPos, nRow1);
     526             : 
     527             :         assert(aPosObj.first->type == sc::element_type_formula);
     528           4 :         ScFormulaCell* pCell = sc::formula_block::at(*aPosObj.first->data, aPosObj.second);
     529           4 :         JoinNewFormulaCell(aPosObj, *pCell);
     530             : 
     531           4 :         aPosObj = maCells.position(aPosObj.first, nRow2);
     532             :         assert(aPosObj.first->type == sc::element_type_formula);
     533           4 :         pCell = sc::formula_block::at(*aPosObj.first->data, aPosObj.second);
     534           4 :         JoinNewFormulaCell(aPosObj, *pCell);
     535             : 
     536           4 :         std::vector<sc::CellTextAttr> aTextAttrs(nLen);
     537           4 :         itAttrPos = maCellTextAttrs.set(itAttrPos, nRow1, aTextAttrs.begin(), aTextAttrs.end());
     538           4 :     }
     539             : 
     540           8 :     CellStorageModified();
     541           4 : }
     542             : 
     543          38 : ScPostIt* ScColumn::ReleaseNote( SCROW nRow )
     544             : {
     545          38 :     if (!ValidRow(nRow))
     546           0 :         return NULL;
     547             : 
     548          38 :     ScPostIt* p = NULL;
     549          38 :     maCellNotes.release(nRow, p);
     550          38 :     return p;
     551             : }
     552             : 
     553        2112 : size_t ScColumn::GetNoteCount() const
     554             : {
     555        2112 :     size_t nCount = 0;
     556        2112 :     sc::CellNoteStoreType::const_iterator it = maCellNotes.begin(), itEnd = maCellNotes.end();
     557        4292 :     for (; it != itEnd; ++it)
     558             :     {
     559        2180 :         if (it->type != sc::element_type_cellnote)
     560        2146 :             continue;
     561             : 
     562          34 :         nCount += it->size;
     563             :     }
     564             : 
     565        2112 :     return nCount;
     566             : }
     567             : 
     568             : namespace {
     569             : 
     570             : class NoteCaptionCreator
     571             : {
     572             :     ScAddress maPos;
     573             : public:
     574       59392 :     NoteCaptionCreator( SCTAB nTab, SCCOL nCol ) : maPos(nCol,0,nTab) {}
     575             : 
     576           8 :     void operator() ( size_t nRow, ScPostIt* p )
     577             :     {
     578           8 :         maPos.SetRow(nRow);
     579           8 :         p->GetOrCreateCaption(maPos);
     580           8 :     }
     581             : };
     582             : 
     583             : struct NoteCaptionCleaner
     584             : {
     585          20 :     void operator() ( size_t /*nRow*/, ScPostIt* p )
     586             :     {
     587          20 :         p->ForgetCaption();
     588          20 :     }
     589             : };
     590             : 
     591             : }
     592             : 
     593       59392 : void ScColumn::CreateAllNoteCaptions()
     594             : {
     595       59392 :     NoteCaptionCreator aFunc(nTab, nCol);
     596       59392 :     sc::ProcessNote(maCellNotes, aFunc);
     597       59392 : }
     598             : 
     599          32 : void ScColumn::ForgetNoteCaptions( SCROW nRow1, SCROW nRow2 )
     600             : {
     601          32 :     if (!ValidRow(nRow1) || !ValidRow(nRow2))
     602          32 :         return;
     603             : 
     604             :     NoteCaptionCleaner aFunc;
     605          32 :     sc::CellNoteStoreType::iterator it = maCellNotes.begin();
     606          32 :     sc::ProcessNote(it, maCellNotes, nRow1, nRow2, aFunc);
     607             : }
     608             : 
     609          12 : SCROW ScColumn::GetNotePosition( size_t nIndex ) const
     610             : {
     611             :     // Return the row position of the nth note in the column.
     612             : 
     613          12 :     sc::CellNoteStoreType::const_iterator it = maCellNotes.begin(), itEnd = maCellNotes.end();
     614             : 
     615          12 :     size_t nCount = 0; // Number of notes encountered so far.
     616          24 :     for (; it != itEnd; ++it)
     617             :     {
     618          24 :         if (it->type != sc::element_type_cellnote)
     619             :             // Skip the empty blocks.
     620          12 :             continue;
     621             : 
     622          12 :         if (nIndex < nCount + it->size)
     623             :         {
     624             :             // Index falls within this block.
     625          12 :             size_t nOffset = nIndex - nCount;
     626          12 :             return it->position + nOffset;
     627             :         }
     628             : 
     629           0 :         nCount += it->size;
     630             :     }
     631             : 
     632           0 :     return -1;
     633             : }
     634             : 
     635             : namespace {
     636             : 
     637             : class NoteEntryCollector
     638             : {
     639             :     std::vector<sc::NoteEntry>& mrNotes;
     640             :     SCTAB mnTab;
     641             :     SCCOL mnCol;
     642             :     SCROW mnStartRow;
     643             :     SCROW mnEndRow;
     644             : public:
     645      327680 :     NoteEntryCollector( std::vector<sc::NoteEntry>& rNotes, SCTAB nTab, SCCOL nCol,
     646             :             SCROW nStartRow = 0, SCROW nEndRow = MAXROW) :
     647             :         mrNotes(rNotes), mnTab(nTab), mnCol(nCol),
     648      327680 :         mnStartRow(nStartRow), mnEndRow(nEndRow) {}
     649             : 
     650      303234 :     void operator() (const sc::CellNoteStoreType::value_type& node) const
     651             :     {
     652      303234 :         if (node.type != sc::element_type_cellnote)
     653      606400 :             return;
     654             : 
     655          68 :         size_t nTopRow = node.position;
     656          68 :         sc::cellnote_block::const_iterator it = sc::cellnote_block::begin(*node.data);
     657          68 :         sc::cellnote_block::const_iterator itEnd = sc::cellnote_block::end(*node.data);
     658          68 :         size_t nOffset = 0;
     659          68 :         if(nTopRow < size_t(mnStartRow))
     660             :         {
     661           0 :             std::advance(it, mnStartRow - nTopRow);
     662           0 :             nOffset = mnStartRow - nTopRow;
     663             :         }
     664             : 
     665         136 :         for (; it != itEnd && nTopRow + nOffset <= size_t(mnEndRow);
     666             :                 ++it, ++nOffset)
     667             :         {
     668          68 :             ScAddress aPos(mnCol, nTopRow + nOffset, mnTab);
     669          68 :             mrNotes.push_back(sc::NoteEntry(aPos, *it));
     670             :         }
     671             :     }
     672             : };
     673             : 
     674             : }
     675             : 
     676      303104 : void ScColumn::GetAllNoteEntries( std::vector<sc::NoteEntry>& rNotes ) const
     677             : {
     678      303104 :     std::for_each(maCellNotes.begin(), maCellNotes.end(), NoteEntryCollector(rNotes, nTab, nCol));
     679      303104 : }
     680             : 
     681       24576 : void ScColumn::GetNotesInRange(SCROW nStartRow, SCROW nEndRow,
     682             :         std::vector<sc::NoteEntry>& rNotes ) const
     683             : {
     684       24576 :     std::pair<sc::CellNoteStoreType::const_iterator,size_t> aPos = maCellNotes.position(nStartRow);
     685       24576 :     sc::CellNoteStoreType::const_iterator it = aPos.first;
     686       24576 :     if (it == maCellNotes.end())
     687             :         // Invalid row number.
     688       24576 :         return;
     689             : 
     690             :     std::pair<sc::CellNoteStoreType::const_iterator,size_t> aEndPos =
     691       24576 :         maCellNotes.position(nEndRow);
     692       24576 :     sc::CellNoteStoreType::const_iterator itEnd = aEndPos.first;
     693             : 
     694       24576 :     std::for_each(it, itEnd, NoteEntryCollector(rNotes, nTab, nCol, nStartRow, nEndRow));
     695             : }
     696             : 
     697             : namespace {
     698             : 
     699             : class RecompileByOpcodeHandler
     700             : {
     701             :     ScDocument* mpDoc;
     702             :     const boost::unordered_set<OpCode>& mrOps;
     703             :     sc::EndListeningContext& mrEndListenCxt;
     704             :     sc::CompileFormulaContext& mrCompileFormulaCxt;
     705             : 
     706             : public:
     707      165888 :     RecompileByOpcodeHandler(
     708             :         ScDocument* pDoc, const boost::unordered_set<OpCode>& rOps,
     709             :         sc::EndListeningContext& rEndListenCxt, sc::CompileFormulaContext& rCompileCxt ) :
     710             :         mpDoc(pDoc),
     711             :         mrOps(rOps),
     712             :         mrEndListenCxt(rEndListenCxt),
     713      165888 :         mrCompileFormulaCxt(rCompileCxt) {}
     714             : 
     715          28 :     void operator() ( sc::FormulaGroupEntry& rEntry )
     716             :     {
     717             :         // Perform end listening, remove from formula tree, and set them up
     718             :         // for re-compilation.
     719             : 
     720          28 :         ScFormulaCell* pTop = NULL;
     721             : 
     722          28 :         if (rEntry.mbShared)
     723             :         {
     724             :             // Only inspect the code from the top cell.
     725          10 :             pTop = *rEntry.mpCells;
     726             :         }
     727             :         else
     728          18 :             pTop = rEntry.mpCell;
     729             : 
     730          28 :         ScTokenArray* pCode = pTop->GetCode();
     731          28 :         bool bRecompile = pCode->HasOpCodes(mrOps);
     732             : 
     733          28 :         if (bRecompile)
     734             :         {
     735             :             // Get the formula string.
     736          10 :             OUString aFormula = pTop->GetFormula(mrCompileFormulaCxt);
     737          10 :             sal_Int32 n = aFormula.getLength();
     738          10 :             if (pTop->GetMatrixFlag() != MM_NONE && n > 0)
     739             :             {
     740           0 :                 if (aFormula[0] == '{' && aFormula[n-1] == '}')
     741           0 :                     aFormula = aFormula.copy(1, n-2);
     742             :             }
     743             : 
     744          10 :             if (rEntry.mbShared)
     745             :             {
     746           8 :                 ScFormulaCell** pp = rEntry.mpCells;
     747           8 :                 ScFormulaCell** ppEnd = pp + rEntry.mnLength;
     748          32 :                 for (; pp != ppEnd; ++pp)
     749             :                 {
     750          24 :                     ScFormulaCell* p = *pp;
     751          24 :                     p->EndListeningTo(mrEndListenCxt);
     752          24 :                     mpDoc->RemoveFromFormulaTree(p);
     753             :                 }
     754             :             }
     755             :             else
     756             :             {
     757           2 :                 rEntry.mpCell->EndListeningTo(mrEndListenCxt);
     758           2 :                 mpDoc->RemoveFromFormulaTree(rEntry.mpCell);
     759             :             }
     760             : 
     761          10 :             pCode->Clear();
     762          10 :             pTop->SetHybridFormula(aFormula, mpDoc->GetGrammar());
     763             :         }
     764          28 :     }
     765             : };
     766             : 
     767             : class CompileHybridFormulaHandler
     768             : {
     769             :     ScDocument* mpDoc;
     770             :     sc::StartListeningContext& mrStartListenCxt;
     771             :     sc::CompileFormulaContext& mrCompileFormulaCxt;
     772             : 
     773             : public:
     774      165888 :     CompileHybridFormulaHandler( ScDocument* pDoc, sc::StartListeningContext& rStartListenCxt, sc::CompileFormulaContext& rCompileCxt ) :
     775             :         mpDoc(pDoc),
     776             :         mrStartListenCxt(rStartListenCxt),
     777      165888 :         mrCompileFormulaCxt(rCompileCxt) {}
     778             : 
     779          28 :     void operator() ( sc::FormulaGroupEntry& rEntry )
     780             :     {
     781          28 :         if (rEntry.mbShared)
     782             :         {
     783          10 :             ScFormulaCell* pTop = *rEntry.mpCells;
     784          10 :             OUString aFormula = pTop->GetHybridFormula();
     785             : 
     786          10 :             if (!aFormula.isEmpty())
     787             :             {
     788             :                 // Create a new token array from the hybrid formula string, and
     789             :                 // set it to the group.
     790           8 :                 ScCompiler aComp(mrCompileFormulaCxt, pTop->aPos);
     791           8 :                 ScTokenArray* pNewCode = aComp.CompileString(aFormula);
     792          16 :                 ScFormulaCellGroupRef xGroup = pTop->GetCellGroup();
     793             :                 assert(xGroup);
     794           8 :                 xGroup->setCode(pNewCode);
     795           8 :                 xGroup->compileCode(*mpDoc, pTop->aPos, mpDoc->GetGrammar());
     796             : 
     797             :                 // Propagate the new token array to all formula cells in the group.
     798           8 :                 ScFormulaCell** pp = rEntry.mpCells;
     799           8 :                 ScFormulaCell** ppEnd = pp + rEntry.mnLength;
     800          32 :                 for (; pp != ppEnd; ++pp)
     801             :                 {
     802          24 :                     ScFormulaCell* p = *pp;
     803          24 :                     p->SyncSharedCode();
     804          24 :                     p->StartListeningTo(mrStartListenCxt);
     805          24 :                     p->SetDirty();
     806           8 :                 }
     807          10 :             }
     808             :         }
     809             :         else
     810             :         {
     811          18 :             ScFormulaCell* pCell = rEntry.mpCell;
     812          18 :             OUString aFormula = pCell->GetHybridFormula();
     813             : 
     814          18 :             if (!aFormula.isEmpty())
     815             :             {
     816             :                 // Create token array from formula string.
     817           2 :                 ScCompiler aComp(mrCompileFormulaCxt, pCell->aPos);
     818           2 :                 ScTokenArray* pNewCode = aComp.CompileString(aFormula);
     819             : 
     820             :                 // Generate RPN tokens.
     821           4 :                 ScCompiler aComp2(mpDoc, pCell->aPos, *pNewCode);
     822           2 :                 aComp2.CompileTokenArray();
     823             : 
     824           2 :                 pCell->SetCode(pNewCode);
     825           2 :                 pCell->StartListeningTo(mrStartListenCxt);
     826           4 :                 pCell->SetDirty();
     827          18 :             }
     828             :         }
     829          28 :     }
     830             : };
     831             : 
     832             : }
     833             : 
     834      143360 : void ScColumn::PreprocessRangeNameUpdate(
     835             :     sc::EndListeningContext& rEndListenCxt, sc::CompileFormulaContext& rCompileCxt )
     836             : {
     837             :     // Collect all formula groups.
     838      143360 :     std::vector<sc::FormulaGroupEntry> aGroups = GetFormulaGroupEntries();
     839             : 
     840      286720 :     boost::unordered_set<OpCode> aOps;
     841      143360 :     aOps.insert(ocBad);
     842      143360 :     aOps.insert(ocColRowName);
     843      143360 :     aOps.insert(ocName);
     844      143360 :     RecompileByOpcodeHandler aFunc(pDocument, aOps, rEndListenCxt, rCompileCxt);
     845      286720 :     std::for_each(aGroups.begin(), aGroups.end(), aFunc);
     846      143360 : }
     847             : 
     848       22528 : void ScColumn::PreprocessDBDataUpdate(
     849             :     sc::EndListeningContext& rEndListenCxt, sc::CompileFormulaContext& rCompileCxt )
     850             : {
     851             :     // Collect all formula groups.
     852       22528 :     std::vector<sc::FormulaGroupEntry> aGroups = GetFormulaGroupEntries();
     853             : 
     854       45056 :     boost::unordered_set<OpCode> aOps;
     855       22528 :     aOps.insert(ocBad);
     856       22528 :     aOps.insert(ocColRowName);
     857       22528 :     aOps.insert(ocDBArea);
     858       22528 :     RecompileByOpcodeHandler aFunc(pDocument, aOps, rEndListenCxt, rCompileCxt);
     859       45056 :     std::for_each(aGroups.begin(), aGroups.end(), aFunc);
     860       22528 : }
     861             : 
     862      165888 : void ScColumn::CompileHybridFormula(
     863             :     sc::StartListeningContext& rStartListenCxt, sc::CompileFormulaContext& rCompileCxt )
     864             : {
     865             :     // Collect all formula groups.
     866      165888 :     std::vector<sc::FormulaGroupEntry> aGroups = GetFormulaGroupEntries();
     867             : 
     868      165888 :     CompileHybridFormulaHandler aFunc(pDocument, rStartListenCxt, rCompileCxt);
     869      165888 :     std::for_each(aGroups.begin(), aGroups.end(), aFunc);
     870      165888 : }
     871             : 
     872             : namespace {
     873             : 
     874             : class ScriptTypeUpdater
     875             : {
     876             :     ScColumn& mrCol;
     877             :     sc::CellTextAttrStoreType& mrTextAttrs;
     878             :     sc::CellTextAttrStoreType::iterator miPosAttr;
     879             :     ScConditionalFormatList* mpCFList;
     880             :     SvNumberFormatter* mpFormatter;
     881             :     ScAddress maPos;
     882             :     bool mbUpdated;
     883             : 
     884             : private:
     885        2955 :     void updateScriptType( size_t nRow, ScRefCellValue& rCell )
     886             :     {
     887        2955 :         sc::CellTextAttrStoreType::position_type aAttrPos = mrTextAttrs.position(miPosAttr, nRow);
     888        2955 :         miPosAttr = aAttrPos.first;
     889             : 
     890        2955 :         if (aAttrPos.first->type != sc::element_type_celltextattr)
     891        2139 :             return;
     892             : 
     893        2955 :         sc::CellTextAttr& rAttr = sc::celltextattr_block::at(*aAttrPos.first->data, aAttrPos.second);
     894        2955 :         if (rAttr.mnScriptType != SC_SCRIPTTYPE_UNKNOWN)
     895             :             // Script type already deteremined.  Skip it.
     896        2139 :             return;
     897             : 
     898         816 :         const ScPatternAttr* pPat = mrCol.GetPattern(nRow);
     899         816 :         if (!pPat)
     900             :             // In theory this should never return NULL. But let's be safe.
     901           0 :             return;
     902             : 
     903         816 :         const SfxItemSet* pCondSet = NULL;
     904         816 :         if (mpCFList)
     905             :         {
     906         816 :             maPos.SetRow(nRow);
     907             :             const ScCondFormatItem& rItem =
     908         816 :                 static_cast<const ScCondFormatItem&>(pPat->GetItem(ATTR_CONDITIONAL));
     909         816 :             const std::vector<sal_uInt32>& rData = rItem.GetCondFormatData();
     910         816 :             pCondSet = mrCol.GetDoc().GetCondResult(rCell, maPos, *mpCFList, rData);
     911             :         }
     912             : 
     913         816 :         OUString aStr;
     914             :         Color* pColor;
     915         816 :         sal_uLong nFormat = pPat->GetNumberFormat(mpFormatter, pCondSet);
     916         816 :         ScCellFormat::GetString(rCell, nFormat, aStr, &pColor, *mpFormatter, &mrCol.GetDoc());
     917             : 
     918         816 :         rAttr.mnScriptType = mrCol.GetDoc().GetStringScriptType(aStr);
     919         816 :         mbUpdated = true;
     920             :     }
     921             : 
     922             : public:
     923     1136778 :     ScriptTypeUpdater( ScColumn& rCol ) :
     924             :         mrCol(rCol),
     925     1136778 :         mrTextAttrs(rCol.GetCellAttrStore()),
     926             :         miPosAttr(mrTextAttrs.begin()),
     927     1136778 :         mpCFList(rCol.GetDoc().GetCondFormList(rCol.GetTab())),
     928     1136778 :         mpFormatter(rCol.GetDoc().GetFormatTable()),
     929     2273556 :         maPos(rCol.GetCol(), 0, rCol.GetTab()),
     930     6820668 :         mbUpdated(false)
     931     1136778 :     {}
     932             : 
     933         598 :     void operator() ( size_t nRow, double fVal )
     934             :     {
     935         598 :         ScRefCellValue aCell(fVal);
     936         598 :         updateScriptType(nRow, aCell);
     937         598 :     }
     938             : 
     939        2123 :     void operator() ( size_t nRow, const svl::SharedString& rStr )
     940             :     {
     941        2123 :         ScRefCellValue aCell(&rStr);
     942        2123 :         updateScriptType(nRow, aCell);
     943        2123 :     }
     944             : 
     945           0 :     void operator() ( size_t nRow, const EditTextObject* pText )
     946             :     {
     947           0 :         ScRefCellValue aCell(pText);
     948           0 :         updateScriptType(nRow, aCell);
     949           0 :     }
     950             : 
     951         234 :     void operator() ( size_t nRow, const ScFormulaCell* pCell )
     952             :     {
     953         234 :         ScRefCellValue aCell(const_cast<ScFormulaCell*>(pCell));
     954         234 :         updateScriptType(nRow, aCell);
     955         234 :     }
     956             : 
     957     1136778 :     bool isUpdated() const { return mbUpdated; }
     958             : };
     959             : 
     960             : }
     961             : 
     962     1136778 : void ScColumn::UpdateScriptTypes( SCROW nRow1, SCROW nRow2 )
     963             : {
     964     1136778 :     if (!ValidRow(nRow1) || !ValidRow(nRow2) || nRow1 > nRow2)
     965     1136778 :         return;
     966             : 
     967     1136778 :     ScriptTypeUpdater aFunc(*this);
     968     1136778 :     sc::ParseAllNonEmpty(maCells.begin(), maCells, nRow1, nRow2, aFunc);
     969     1136778 :     if (aFunc.isUpdated())
     970         366 :         CellStorageModified();
     971             : }
     972             : 
     973          34 : void ScColumn::Swap( ScColumn& rOther, SCROW nRow1, SCROW nRow2, bool bPattern )
     974             : {
     975          34 :     maCells.swap(nRow1, nRow2, rOther.maCells, nRow1);
     976          34 :     maCellTextAttrs.swap(nRow1, nRow2, rOther.maCellTextAttrs, nRow1);
     977          34 :     maCellNotes.swap(nRow1, nRow2, rOther.maCellNotes, nRow1);
     978          34 :     maBroadcasters.swap(nRow1, nRow2, rOther.maBroadcasters, nRow1);
     979             : 
     980          34 :     if (bPattern)
     981             :     {
     982    18874430 :         for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
     983             :         {
     984    18874396 :             const ScPatternAttr* pPat1 = GetPattern(nRow);
     985    18874396 :             const ScPatternAttr* pPat2 = rOther.GetPattern(nRow);
     986    18874396 :             if (pPat1 != pPat2)
     987             :             {
     988           0 :                 SetPattern(nRow, *pPat2, true);
     989           0 :                 rOther.SetPattern(nRow, *pPat1, true);
     990             :             }
     991             :         }
     992             :     }
     993             : 
     994          34 :     CellStorageModified();
     995          34 :     rOther.CellStorageModified();
     996          34 : }
     997             : 
     998             : namespace {
     999             : 
    1000             : class FormulaColPosSetter
    1001             : {
    1002             :     SCCOL mnCol;
    1003             : public:
    1004          72 :     FormulaColPosSetter( SCCOL nCol ) : mnCol(nCol) {}
    1005             : 
    1006           6 :     void operator() ( size_t nRow, ScFormulaCell* pCell )
    1007             :     {
    1008           6 :         if (!pCell->IsShared() || pCell->IsSharedTop())
    1009             :         {
    1010             :             // Ensure that the references still point to the same locations
    1011             :             // after the position change.
    1012           2 :             ScAddress aOldPos = pCell->aPos;
    1013           2 :             pCell->aPos.SetCol(mnCol);
    1014           2 :             pCell->aPos.SetRow(nRow);
    1015           2 :             pCell->GetCode()->AdjustReferenceOnMovedOrigin(aOldPos, pCell->aPos);
    1016             :         }
    1017             :         else
    1018             :         {
    1019           4 :             pCell->aPos.SetCol(mnCol);
    1020           4 :             pCell->aPos.SetRow(nRow);
    1021             :         }
    1022           6 :     }
    1023             : };
    1024             : 
    1025             : }
    1026             : 
    1027          72 : void ScColumn::ResetFormulaCellPositions( SCROW nRow1, SCROW nRow2 )
    1028             : {
    1029          72 :     FormulaColPosSetter aFunc(nCol);
    1030          72 :     sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc);
    1031          72 : }
    1032             : 
    1033             : namespace {
    1034             : 
    1035          72 : class RelativeRefBoundChecker
    1036             : {
    1037             :     std::vector<SCROW> maBounds;
    1038             :     ScRange maBoundRange;
    1039             : 
    1040             : public:
    1041          72 :     RelativeRefBoundChecker( const ScRange& rBoundRange ) :
    1042          72 :         maBoundRange(rBoundRange) {}
    1043             : 
    1044           6 :     void operator() ( size_t /*nRow*/, ScFormulaCell* pCell )
    1045             :     {
    1046           6 :         if (!pCell->IsSharedTop())
    1047          10 :             return;
    1048             : 
    1049             :         pCell->GetCode()->CheckRelativeReferenceBounds(
    1050           2 :             pCell->aPos, pCell->GetSharedLength(), maBoundRange, maBounds);
    1051             :     }
    1052             : 
    1053          72 :     void swapBounds( std::vector<SCROW>& rBounds )
    1054             :     {
    1055          72 :         rBounds.swap(maBounds);
    1056          72 :     }
    1057             : };
    1058             : 
    1059             : }
    1060             : 
    1061          72 : void ScColumn::SplitFormulaGroupByRelativeRef( const ScRange& rBoundRange )
    1062             : {
    1063          72 :     if (rBoundRange.aStart.Row() >= MAXROW)
    1064             :         // Nothing to split.
    1065          72 :         return;
    1066             : 
    1067          72 :     std::vector<SCROW> aBounds;
    1068             : 
    1069             :     // Cut at row boundaries first.
    1070          72 :     aBounds.push_back(rBoundRange.aStart.Row());
    1071          72 :     if (rBoundRange.aEnd.Row() < MAXROW)
    1072          42 :         aBounds.push_back(rBoundRange.aEnd.Row()+1);
    1073          72 :     sc::SharedFormulaUtil::splitFormulaCellGroups(maCells, aBounds);
    1074             : 
    1075         144 :     RelativeRefBoundChecker aFunc(rBoundRange);
    1076             :     sc::ProcessFormula(
    1077          72 :         maCells.begin(), maCells, rBoundRange.aStart.Row(), rBoundRange.aEnd.Row(), aFunc);
    1078          72 :     aFunc.swapBounds(aBounds);
    1079         144 :     sc::SharedFormulaUtil::splitFormulaCellGroups(maCells, aBounds);
    1080             : }
    1081             : 
    1082             : namespace {
    1083             : 
    1084             : class ListenerCollector
    1085             : {
    1086             :     std::vector<SvtListener*>& mrListeners;
    1087             : public:
    1088        2280 :     ListenerCollector( std::vector<SvtListener*>& rListener ) :
    1089        2280 :         mrListeners(rListener) {}
    1090             : 
    1091         222 :     void operator() ( size_t /*nRow*/, SvtBroadcaster* p )
    1092             :     {
    1093         222 :         SvtBroadcaster::ListenersType& rLis = p->GetAllListeners();
    1094         222 :         std::copy(rLis.begin(), rLis.end(), std::back_inserter(mrListeners));
    1095         222 :     }
    1096             : };
    1097             : 
    1098             : }
    1099             : 
    1100        2280 : void ScColumn::CollectListeners( std::vector<SvtListener*>& rListeners, SCROW nRow1, SCROW nRow2 )
    1101             : {
    1102        2280 :     if (nRow2 < nRow1 || !ValidRow(nRow1) || !ValidRow(nRow2))
    1103        2280 :         return;
    1104             : 
    1105        2280 :     ListenerCollector aFunc(rListeners);
    1106        2280 :     sc::ProcessBroadcaster(maBroadcasters.begin(), maBroadcasters, nRow1, nRow2, aFunc);
    1107             : }
    1108             : 
    1109             : namespace {
    1110             : 
    1111             : struct FindAnyFormula
    1112             : {
    1113           0 :     bool operator() ( size_t /*nRow*/, const ScFormulaCell* /*pCell*/ ) const
    1114             :     {
    1115           0 :         return true;
    1116             :     }
    1117             : };
    1118             : 
    1119             : }
    1120             : 
    1121           0 : bool ScColumn::HasFormulaCell( SCROW nRow1, SCROW nRow2 ) const
    1122             : {
    1123           0 :     if (nRow2 < nRow1 || !ValidRow(nRow1) || !ValidRow(nRow2))
    1124           0 :         return false;
    1125             : 
    1126             :     FindAnyFormula aFunc;
    1127             :     std::pair<sc::CellStoreType::const_iterator, size_t> aRet =
    1128           0 :         sc::FindFormula(maCells, nRow1, nRow2, aFunc);
    1129             : 
    1130           0 :     return aRet.first != maCells.end();
    1131         228 : }
    1132             : 
    1133             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10