LCOV - code coverage report
Current view: top level - sc/source/core/data - column4.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 244 355 68.7 %
Date: 2014-04-11 Functions: 24 28 85.7 %
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 <clipcontext.hxx>
      12             : #include <clipparam.hxx>
      13             : #include <cellvalue.hxx>
      14             : #include <attarray.hxx>
      15             : #include <document.hxx>
      16             : #include <cellvalues.hxx>
      17             : #include <columnspanset.hxx>
      18             : #include <listenercontext.hxx>
      19             : #include <tokenstringcontext.hxx>
      20             : #include <mtvcellfunc.hxx>
      21             : #include <clipcontext.hxx>
      22             : #include <attrib.hxx>
      23             : #include <patattr.hxx>
      24             : #include <docpool.hxx>
      25             : #include <conditio.hxx>
      26             : #include <formulagroup.hxx>
      27             : #include <tokenarray.hxx>
      28             : 
      29             : #include <svl/sharedstringpool.hxx>
      30             : 
      31             : #include <vector>
      32             : #include <cassert>
      33             : 
      34             : #include <boost/shared_ptr.hpp>
      35             : 
      36           2 : bool ScColumn::IsMerged( SCROW nRow ) const
      37             : {
      38           2 :     return pAttrArray->IsMerged(nRow);
      39             : }
      40             : 
      41           1 : void ScColumn::DeleteBeforeCopyFromClip( sc::CopyFromClipContext& rCxt, const ScColumn& rClipCol )
      42             : {
      43           1 :     sc::CopyFromClipContext::Range aRange = rCxt.getDestRange();
      44           1 :     if (!ValidRow(aRange.mnRow1) || !ValidRow(aRange.mnRow2))
      45           1 :         return;
      46             : 
      47           1 :     ScRange aClipRange = rCxt.getClipDoc()->GetClipParam().getWholeRange();
      48           1 :     SCROW nClipRow1 = aClipRange.aStart.Row();
      49           1 :     SCROW nClipRow2 = aClipRange.aEnd.Row();
      50           1 :     SCROW nClipRowLen = nClipRow2 - nClipRow1 + 1;
      51             : 
      52             :     // Check for non-empty cell ranges in the clip column.
      53           1 :     sc::SingleColumnSpanSet aSpanSet;
      54           1 :     aSpanSet.scan(rClipCol, nClipRow1, nClipRow2);
      55           2 :     sc::SingleColumnSpanSet::SpansType aSpans;
      56           1 :     aSpanSet.getSpans(aSpans);
      57             : 
      58             :     // Translate the clip column spans into the destination column, and repeat as needed.
      59           2 :     std::vector<sc::RowSpan> aDestSpans;
      60           1 :     SCROW nDestOffset = aRange.mnRow1 - nClipRow1;
      61           1 :     bool bContinue = true;
      62           4 :     while (bContinue)
      63             :     {
      64           2 :         sc::SingleColumnSpanSet::SpansType::const_iterator it = aSpans.begin(), itEnd = aSpans.end();
      65           6 :         for (; it != itEnd && bContinue; ++it)
      66             :         {
      67           4 :             const sc::RowSpan& r = *it;
      68           4 :             SCROW nDestRow1 = r.mnRow1 + nDestOffset;
      69           4 :             SCROW nDestRow2 = r.mnRow2 + nDestOffset;
      70             : 
      71           4 :             if (nDestRow1 > aRange.mnRow2)
      72             :             {
      73             :                 // We're done.
      74           1 :                 bContinue = false;
      75           1 :                 continue;
      76             :             }
      77             : 
      78           3 :             if (nDestRow2 > aRange.mnRow2)
      79             :             {
      80             :                 // Truncate this range, and set it as the last span.
      81           0 :                 nDestRow2 = aRange.mnRow2;
      82           0 :                 bContinue = false;
      83             :             }
      84             : 
      85           3 :             aDestSpans.push_back(sc::RowSpan(nDestRow1, nDestRow2));
      86             :         }
      87             : 
      88           2 :         nDestOffset += nClipRowLen;
      89             :     }
      90             : 
      91           2 :     std::vector<SCROW> aDeletedRows;
      92           1 :     sal_uInt16 nDelFlag = rCxt.getDeleteFlag();
      93           1 :     sc::ColumnBlockPosition aBlockPos;
      94           1 :     InitBlockPosition(aBlockPos);
      95             : 
      96           1 :     std::vector<sc::RowSpan>::const_iterator it = aDestSpans.begin(), itEnd = aDestSpans.end();
      97           4 :     for (; it != itEnd; ++it)
      98             :     {
      99           3 :         SCROW nRow1 = it->mnRow1;
     100           3 :         SCROW nRow2 = it->mnRow2;
     101             : 
     102           3 :         if (nDelFlag & IDF_CONTENTS)
     103           3 :             DeleteCells(aBlockPos, nRow1, nRow2, nDelFlag, aDeletedRows);
     104             : 
     105           3 :         if (nDelFlag & IDF_NOTE)
     106           3 :             DeleteCellNotes(aBlockPos, nRow1, nRow2);
     107             : 
     108           3 :         if (nDelFlag & IDF_EDITATTR)
     109           0 :             RemoveEditAttribs(nRow1, nRow2);
     110             : 
     111             :         // Delete attributes just now
     112           3 :         if (nDelFlag & IDF_ATTRIB)
     113             :         {
     114           3 :             pAttrArray->DeleteArea(nRow1, nRow2);
     115             : 
     116           3 :             if (rCxt.isTableProtected())
     117             :             {
     118           0 :                 ScPatternAttr aPattern(pDocument->GetPool());
     119           0 :                 aPattern.GetItemSet().Put(ScProtectionAttr(false));
     120           0 :                 ApplyPatternArea(nRow1, nRow2, aPattern);
     121             :             }
     122             : 
     123           3 :             ScConditionalFormatList* pCondList = rCxt.getCondFormatList();
     124           3 :             if (pCondList)
     125           3 :                 pCondList->DeleteArea(nCol, nRow1, nCol, nRow2);
     126             :         }
     127           0 :         else if ((nDelFlag & IDF_HARDATTR) == IDF_HARDATTR)
     128           0 :             pAttrArray->DeleteHardAttr(nRow1, nRow2);
     129             :     }
     130             : 
     131           2 :     BroadcastCells(aDeletedRows, SC_HINT_DATACHANGED);
     132             : }
     133             : 
     134           2 : void ScColumn::CopyOneCellFromClip( sc::CopyFromClipContext& rCxt, SCROW nRow1, SCROW nRow2 )
     135             : {
     136             :     assert(nRow1 <= nRow2);
     137             : 
     138           2 :     size_t nDestSize = nRow2 - nRow1 + 1;
     139           2 :     sc::ColumnBlockPosition* pBlockPos = rCxt.getBlockPosition(nTab, nCol);
     140           2 :     if (!pBlockPos)
     141           2 :         return;
     142             : 
     143           2 :     ScCellValue& rSrcCell = rCxt.getSingleCell();
     144             : 
     145           2 :     sal_uInt16 nFlags = rCxt.getInsertFlag();
     146             : 
     147           2 :     if ((nFlags & IDF_ATTRIB) != 0)
     148             :     {
     149           2 :         if (!rCxt.isSkipAttrForEmptyCells() || rSrcCell.meType != CELLTYPE_NONE)
     150             :         {
     151           2 :             const ScPatternAttr* pAttr = rCxt.getSingleCellPattern();
     152           2 :             pAttrArray->SetPatternArea(nRow1, nRow2, pAttr, true);
     153             :         }
     154             :     }
     155             : 
     156           2 :     if ((nFlags & IDF_CONTENTS) != 0)
     157             :     {
     158           2 :         std::vector<sc::CellTextAttr> aTextAttrs(nDestSize);
     159             : 
     160           2 :         switch (rSrcCell.meType)
     161             :         {
     162             :             case CELLTYPE_VALUE:
     163             :             {
     164           0 :                 std::vector<double> aVals(nDestSize, rSrcCell.mfValue);
     165           0 :                 pBlockPos->miCellPos =
     166           0 :                     maCells.set(pBlockPos->miCellPos, nRow1, aVals.begin(), aVals.end());
     167           0 :                 pBlockPos->miCellTextAttrPos =
     168           0 :                     maCellTextAttrs.set(pBlockPos->miCellTextAttrPos, nRow1, aTextAttrs.begin(), aTextAttrs.end());
     169           0 :                 CellStorageModified();
     170             :             }
     171           0 :             break;
     172             :             case CELLTYPE_STRING:
     173             :             {
     174             :                 // Compare the ScDocumentPool* to determine if we are copying within the
     175             :                 // same document. If not, re-intern shared strings.
     176           1 :                 svl::SharedStringPool* pSharedStringPool = (rCxt.getClipDoc()->GetPool() != pDocument->GetPool()) ?
     177           1 :                     &pDocument->GetSharedStringPool() : NULL;
     178             :                 svl::SharedString aStr = (pSharedStringPool ?
     179             :                         pSharedStringPool->intern( rSrcCell.mpString->getString()) :
     180           1 :                         *rSrcCell.mpString);
     181             : 
     182           2 :                 std::vector<svl::SharedString> aStrs(nDestSize, aStr);
     183           2 :                 pBlockPos->miCellPos =
     184           1 :                     maCells.set(pBlockPos->miCellPos, nRow1, aStrs.begin(), aStrs.end());
     185           2 :                 pBlockPos->miCellTextAttrPos =
     186           1 :                     maCellTextAttrs.set(pBlockPos->miCellTextAttrPos, nRow1, aTextAttrs.begin(), aTextAttrs.end());
     187           2 :                 CellStorageModified();
     188             :             }
     189           1 :             break;
     190             :             case CELLTYPE_EDIT:
     191             :             {
     192           0 :                 std::vector<EditTextObject*> aStrs;
     193           0 :                 aStrs.reserve(nDestSize);
     194           0 :                 for (size_t i = 0; i < nDestSize; ++i)
     195           0 :                     aStrs.push_back(rSrcCell.mpEditText->Clone());
     196             : 
     197           0 :                 pBlockPos->miCellPos =
     198           0 :                     maCells.set(pBlockPos->miCellPos, nRow1, aStrs.begin(), aStrs.end());
     199           0 :                 pBlockPos->miCellTextAttrPos =
     200           0 :                     maCellTextAttrs.set(pBlockPos->miCellTextAttrPos, nRow1, aTextAttrs.begin(), aTextAttrs.end());
     201           0 :                 CellStorageModified();
     202             :             }
     203           0 :             break;
     204             :             case CELLTYPE_FORMULA:
     205             :             {
     206           1 :                 std::vector<sc::RowSpan> aRanges;
     207           1 :                 aRanges.reserve(1);
     208           1 :                 aRanges.push_back(sc::RowSpan(nRow1, nRow2));
     209           1 :                 CloneFormulaCell(*rSrcCell.mpFormula, aRanges);
     210             :             }
     211           1 :             break;
     212             :             default:
     213             :                 ;
     214           2 :         }
     215             :     }
     216             : 
     217           2 :     const ScPostIt* pNote = rCxt.getSingleCellNote();
     218           2 :     if (pNote && (nFlags & (IDF_NOTE | IDF_ADDNOTES)) != 0)
     219             :     {
     220             :         // Duplicate the cell note over the whole pasted range.
     221             : 
     222           0 :         ScDocument* pClipDoc = rCxt.getClipDoc();
     223           0 :         const ScAddress& rSrcPos = pClipDoc->GetClipParam().getWholeRange().aStart;
     224           0 :         std::vector<ScPostIt*> aNotes;
     225           0 :         ScAddress aDestPos(nCol, nRow1, nTab);
     226           0 :         aNotes.reserve(nDestSize);
     227           0 :         for (size_t i = 0; i < nDestSize; ++i)
     228             :         {
     229           0 :             bool bCloneCaption = (nFlags & IDF_NOCAPTIONS) == 0;
     230           0 :             aNotes.push_back(pNote->Clone(rSrcPos, *pDocument, aDestPos, bCloneCaption));
     231           0 :             aDestPos.IncRow();
     232             :         }
     233             : 
     234           0 :         pBlockPos->miCellNotePos =
     235             :             maCellNotes.set(
     236           0 :                 pBlockPos->miCellNotePos, nRow1, aNotes.begin(), aNotes.end());
     237             :     }
     238             : }
     239             : 
     240           0 : void ScColumn::SetValues( SCROW nRow, const std::vector<double>& rVals )
     241             : {
     242           0 :     if (!ValidRow(nRow))
     243           0 :         return;
     244             : 
     245           0 :     SCROW nLastRow = nRow + rVals.size() - 1;
     246           0 :     if (nLastRow > MAXROW)
     247             :         // Out of bound. Do nothing.
     248           0 :         return;
     249             : 
     250           0 :     sc::CellStoreType::position_type aPos = maCells.position(nRow);
     251           0 :     DetachFormulaCells(aPos, rVals.size());
     252             : 
     253           0 :     maCells.set(nRow, rVals.begin(), rVals.end());
     254           0 :     std::vector<sc::CellTextAttr> aDefaults(rVals.size());
     255           0 :     maCellTextAttrs.set(nRow, aDefaults.begin(), aDefaults.end());
     256             : 
     257           0 :     CellStorageModified();
     258             : 
     259           0 :     std::vector<SCROW> aRows;
     260           0 :     aRows.reserve(rVals.size());
     261           0 :     for (SCROW i = nRow; i <= nLastRow; ++i)
     262           0 :         aRows.push_back(i);
     263             : 
     264           0 :     BroadcastCells(aRows, SC_HINT_DATACHANGED);
     265             : }
     266             : 
     267           0 : void ScColumn::TransferCellValuesTo( SCROW nRow, size_t nLen, sc::CellValues& rDest )
     268             : {
     269           0 :     if (!ValidRow(nRow))
     270           0 :         return;
     271             : 
     272           0 :     SCROW nLastRow = nRow + nLen - 1;
     273           0 :     if (nLastRow > MAXROW)
     274             :         // Out of bound. Do nothing.
     275           0 :         return;
     276             : 
     277           0 :     sc::CellStoreType::position_type aPos = maCells.position(nRow);
     278           0 :     DetachFormulaCells(aPos, nLen);
     279             : 
     280           0 :     rDest.transferFrom(*this, nRow, nLen);
     281             : 
     282           0 :     std::vector<sc::CellTextAttr> aDefaults(nLen);
     283           0 :     maCellTextAttrs.set(nRow, aDefaults.begin(), aDefaults.end());
     284             : 
     285           0 :     CellStorageModified();
     286             : 
     287           0 :     std::vector<SCROW> aRows;
     288           0 :     aRows.reserve(nLen);
     289           0 :     for (SCROW i = nRow; i <= nLastRow; ++i)
     290           0 :         aRows.push_back(i);
     291             : 
     292           0 :     BroadcastCells(aRows, SC_HINT_DATACHANGED);
     293             : }
     294             : 
     295           0 : void ScColumn::CopyCellValuesFrom( SCROW nRow, const sc::CellValues& rSrc )
     296             : {
     297           0 :     if (!ValidRow(nRow))
     298           0 :         return;
     299             : 
     300           0 :     SCROW nLastRow = nRow + rSrc.size() - 1;
     301           0 :     if (nLastRow > MAXROW)
     302             :         // Out of bound. Do nothing
     303           0 :         return;
     304             : 
     305           0 :     sc::CellStoreType::position_type aPos = maCells.position(nRow);
     306           0 :     DetachFormulaCells(aPos, rSrc.size());
     307             : 
     308           0 :     rSrc.copyTo(*this, nRow);
     309             : 
     310           0 :     std::vector<sc::CellTextAttr> aDefaults(rSrc.size());
     311           0 :     maCellTextAttrs.set(nRow, aDefaults.begin(), aDefaults.end());
     312             : 
     313           0 :     CellStorageModified();
     314             : 
     315           0 :     std::vector<SCROW> aRows;
     316           0 :     aRows.reserve(rSrc.size());
     317           0 :     for (SCROW i = nRow; i <= nLastRow; ++i)
     318           0 :         aRows.push_back(i);
     319             : 
     320           0 :     BroadcastCells(aRows, SC_HINT_DATACHANGED);
     321             : }
     322             : 
     323           0 : void ScColumn::DeleteRanges( const std::vector<sc::RowSpan>& rRanges, sal_uInt16 nDelFlag, bool bBroadcast )
     324             : {
     325           0 :     std::vector<sc::RowSpan>::const_iterator itSpan = rRanges.begin(), itSpanEnd = rRanges.end();
     326           0 :     for (; itSpan != itSpanEnd; ++itSpan)
     327           0 :         DeleteArea(itSpan->mnRow1, itSpan->mnRow2, nDelFlag, bBroadcast);
     328           0 : }
     329             : 
     330           1 : void ScColumn::CloneFormulaCell( const ScFormulaCell& rSrc, const std::vector<sc::RowSpan>& rRanges )
     331             : {
     332           1 :     sc::CellStoreType::iterator itPos = maCells.begin();
     333           1 :     sc::CellTextAttrStoreType::iterator itAttrPos = maCellTextAttrs.begin();
     334           1 :     sc::StartListeningContext aCxt(*pDocument);
     335             : 
     336           2 :     std::vector<ScFormulaCell*> aFormulas;
     337           1 :     std::vector<sc::RowSpan>::const_iterator itSpan = rRanges.begin(), itSpanEnd = rRanges.end();
     338           2 :     for (; itSpan != itSpanEnd; ++itSpan)
     339             :     {
     340           1 :         SCROW nRow1 = itSpan->mnRow1, nRow2 = itSpan->mnRow2;
     341           1 :         size_t nLen = nRow2 - nRow1 + 1;
     342             :         assert(nLen > 0);
     343           1 :         aFormulas.clear();
     344           1 :         aFormulas.reserve(nLen);
     345             : 
     346           1 :         ScAddress aPos(nCol, nRow1, nTab);
     347             : 
     348           1 :         if (nLen == 1)
     349             :         {
     350             :             // Single, ungrouped formula cell.
     351             :             ScFormulaCell* pCell =
     352           1 :                 new ScFormulaCell(rSrc, *pDocument, aPos, pDocument->GetGrammar());
     353           1 :             pCell->StartListeningTo(aCxt);
     354           1 :             pCell->SetDirty();
     355           1 :             aFormulas.push_back(pCell);
     356             :         }
     357             :         else
     358             :         {
     359             :             // Create a group of formula cells.
     360           0 :             ScFormulaCellGroupRef xGroup(new ScFormulaCellGroup);
     361           0 :             xGroup->setCode(*rSrc.GetCode());
     362           0 :             xGroup->compileCode(*pDocument, aPos, pDocument->GetGrammar());
     363           0 :             for (size_t i = 0; i < nLen; ++i, aPos.IncRow())
     364             :             {
     365           0 :                 ScFormulaCell* pCell = new ScFormulaCell(pDocument, aPos, xGroup);
     366           0 :                 if (i == 0)
     367             :                 {
     368           0 :                     xGroup->mpTopCell = pCell;
     369           0 :                     xGroup->mnLength = nLen;
     370             :                 }
     371           0 :                 pCell->StartListeningTo(aCxt);
     372           0 :                 pCell->SetDirty();
     373           0 :                 aFormulas.push_back(pCell);
     374           0 :             }
     375             :         }
     376             : 
     377           1 :         itPos = maCells.set(itPos, nRow1, aFormulas.begin(), aFormulas.end());
     378             : 
     379             :         // Join the top and bottom of the pasted formula cells as needed.
     380           1 :         sc::CellStoreType::position_type aPosObj = maCells.position(itPos, nRow1);
     381             : 
     382             :         assert(aPosObj.first->type == sc::element_type_formula);
     383           1 :         ScFormulaCell* pCell = sc::formula_block::at(*aPosObj.first->data, aPosObj.second);
     384           1 :         JoinNewFormulaCell(aPosObj, *pCell);
     385             : 
     386           1 :         aPosObj = maCells.position(aPosObj.first, nRow2);
     387             :         assert(aPosObj.first->type == sc::element_type_formula);
     388           1 :         pCell = sc::formula_block::at(*aPosObj.first->data, aPosObj.second);
     389           1 :         JoinNewFormulaCell(aPosObj, *pCell);
     390             : 
     391           1 :         std::vector<sc::CellTextAttr> aTextAttrs(nLen);
     392           1 :         itAttrPos = maCellTextAttrs.set(itAttrPos, nRow1, aTextAttrs.begin(), aTextAttrs.end());
     393           1 :     }
     394             : 
     395           2 :     CellStorageModified();
     396           1 : }
     397             : 
     398          12 : ScPostIt* ScColumn::ReleaseNote( SCROW nRow )
     399             : {
     400          12 :     if (!ValidRow(nRow))
     401           0 :         return NULL;
     402             : 
     403          12 :     ScPostIt* p = NULL;
     404          12 :     maCellNotes.release(nRow, p);
     405          12 :     return p;
     406             : }
     407             : 
     408        1050 : size_t ScColumn::GetNoteCount() const
     409             : {
     410        1050 :     size_t nCount = 0;
     411        1050 :     sc::CellNoteStoreType::const_iterator it = maCellNotes.begin(), itEnd = maCellNotes.end();
     412        2130 :     for (; it != itEnd; ++it)
     413             :     {
     414        1080 :         if (it->type != sc::element_type_cellnote)
     415        1065 :             continue;
     416             : 
     417          15 :         nCount += it->size;
     418             :     }
     419             : 
     420        1050 :     return nCount;
     421             : }
     422             : 
     423             : namespace {
     424             : 
     425             : class NoteCaptionCreator
     426             : {
     427             :     ScAddress maPos;
     428             : public:
     429       23552 :     NoteCaptionCreator( SCTAB nTab, SCCOL nCol ) : maPos(nCol,0,nTab) {}
     430             : 
     431           4 :     void operator() ( size_t nRow, ScPostIt* p )
     432             :     {
     433           4 :         maPos.SetRow(nRow);
     434           4 :         p->GetOrCreateCaption(maPos);
     435           4 :     }
     436             : };
     437             : 
     438             : struct NoteCaptionCleaner
     439             : {
     440          10 :     void operator() ( size_t /*nRow*/, ScPostIt* p )
     441             :     {
     442          10 :         p->ForgetCaption();
     443          10 :     }
     444             : };
     445             : 
     446             : }
     447             : 
     448       23552 : void ScColumn::CreateAllNoteCaptions()
     449             : {
     450       23552 :     NoteCaptionCreator aFunc(nTab, nCol);
     451       23552 :     sc::ProcessNote(maCellNotes, aFunc);
     452       23552 : }
     453             : 
     454          15 : void ScColumn::ForgetNoteCaptions( SCROW nRow1, SCROW nRow2 )
     455             : {
     456          15 :     if (!ValidRow(nRow1) || !ValidRow(nRow2))
     457          15 :         return;
     458             : 
     459             :     NoteCaptionCleaner aFunc;
     460          15 :     sc::CellNoteStoreType::iterator it = maCellNotes.begin();
     461          15 :     sc::ProcessNote(it, maCellNotes, nRow1, nRow2, aFunc);
     462             : }
     463             : 
     464           5 : SCROW ScColumn::GetNotePosition( size_t nIndex ) const
     465             : {
     466             :     // Return the row position of the nth note in the column.
     467             : 
     468           5 :     sc::CellNoteStoreType::const_iterator it = maCellNotes.begin(), itEnd = maCellNotes.end();
     469             : 
     470           5 :     size_t nCount = 0; // Number of notes encountered so far.
     471          10 :     for (; it != itEnd; ++it)
     472             :     {
     473          10 :         if (it->type != sc::element_type_cellnote)
     474             :             // Skip the empty blocks.
     475           5 :             continue;
     476             : 
     477           5 :         if (nIndex < nCount + it->size)
     478             :         {
     479             :             // Index falls within this block.
     480           5 :             size_t nOffset = nIndex - nCount;
     481           5 :             return it->position + nOffset;
     482             :         }
     483             : 
     484           0 :         nCount += it->size;
     485             :     }
     486             : 
     487           0 :     return -1;
     488             : }
     489             : 
     490             : namespace {
     491             : 
     492             : class NoteEntryCollector
     493             : {
     494             :     std::vector<sc::NoteEntry>& mrNotes;
     495             :     SCTAB mnTab;
     496             :     SCCOL mnCol;
     497             :     SCROW mnStartRow;
     498             :     SCROW mnEndRow;
     499             : public:
     500      118784 :     NoteEntryCollector( std::vector<sc::NoteEntry>& rNotes, SCTAB nTab, SCCOL nCol,
     501             :             SCROW nStartRow = 0, SCROW nEndRow = MAXROW) :
     502             :         mrNotes(rNotes), mnTab(nTab), mnCol(nCol),
     503      118784 :         mnStartRow(nStartRow), mnEndRow(nEndRow) {}
     504             : 
     505      106561 :     void operator() (const sc::CellNoteStoreType::value_type& node) const
     506             :     {
     507      106561 :         if (node.type != sc::element_type_cellnote)
     508      213088 :             return;
     509             : 
     510          34 :         size_t nTopRow = node.position;
     511          34 :         sc::cellnote_block::const_iterator it = sc::cellnote_block::begin(*node.data);
     512          34 :         sc::cellnote_block::const_iterator itEnd = sc::cellnote_block::end(*node.data);
     513          34 :         size_t nOffset = 0;
     514          34 :         if(nTopRow < size_t(mnStartRow))
     515             :         {
     516           0 :             std::advance(it, mnStartRow - nTopRow);
     517           0 :             nOffset = mnStartRow - nTopRow;
     518             :         }
     519             : 
     520          68 :         for (; it != itEnd && nTopRow + nOffset <= size_t(mnEndRow);
     521             :                 ++it, ++nOffset)
     522             :         {
     523          34 :             ScAddress aPos(mnCol, nTopRow + nOffset, mnTab);
     524          34 :             mrNotes.push_back(sc::NoteEntry(aPos, *it));
     525             :         }
     526             :     }
     527             : };
     528             : 
     529             : }
     530             : 
     531      106496 : void ScColumn::GetAllNoteEntries( std::vector<sc::NoteEntry>& rNotes ) const
     532             : {
     533      106496 :     std::for_each(maCellNotes.begin(), maCellNotes.end(), NoteEntryCollector(rNotes, nTab, nCol));
     534      106496 : }
     535             : 
     536       12288 : void ScColumn::GetNotesInRange(SCROW nStartRow, SCROW nEndRow,
     537             :         std::vector<sc::NoteEntry>& rNotes ) const
     538             : {
     539       12288 :     std::pair<sc::CellNoteStoreType::const_iterator,size_t> aPos = maCellNotes.position(nStartRow);
     540       12288 :     sc::CellNoteStoreType::const_iterator it = aPos.first;
     541       12288 :     if (it == maCellNotes.end())
     542             :         // Invalid row number.
     543       12288 :         return;
     544             : 
     545             :     std::pair<sc::CellNoteStoreType::const_iterator,size_t> aEndPos =
     546       12288 :         maCellNotes.position(nEndRow);
     547       12288 :     sc::CellNoteStoreType::const_iterator itEnd = aEndPos.first;
     548             : 
     549       12288 :     std::for_each(it, itEnd, NoteEntryCollector(rNotes, nTab, nCol, nStartRow, nEndRow));
     550             : }
     551             : 
     552             : namespace {
     553             : 
     554             : class PreRangeNameUpdateHandler
     555             : {
     556             :     ScDocument* mpDoc;
     557             :     sc::EndListeningContext& mrEndListenCxt;
     558             :     sc::CompileFormulaContext& mrCompileFormulaCxt;
     559             : 
     560             : public:
     561       71680 :     PreRangeNameUpdateHandler( ScDocument* pDoc, sc::EndListeningContext& rEndListenCxt, sc::CompileFormulaContext& rCompileCxt ) :
     562             :         mpDoc(pDoc),
     563             :         mrEndListenCxt(rEndListenCxt),
     564       71680 :         mrCompileFormulaCxt(rCompileCxt) {}
     565             : 
     566           4 :     void operator() ( sc::FormulaGroupEntry& rEntry )
     567             :     {
     568             :         // Perform end listening, remove from formula tree, and set them up
     569             :         // for re-compilation.
     570             : 
     571           4 :         ScFormulaCell* pTop = NULL;
     572             : 
     573           4 :         if (rEntry.mbShared)
     574             :         {
     575             :             // Only inspect the code from the top cell.
     576           2 :             pTop = *rEntry.mpCells;
     577             :         }
     578             :         else
     579           2 :             pTop = rEntry.mpCell;
     580             : 
     581           4 :         ScTokenArray* pCode = pTop->GetCode();
     582             : 
     583           4 :         boost::unordered_set<OpCode> aOps;
     584           4 :         aOps.insert(ocBad);
     585           4 :         aOps.insert(ocColRowName);
     586           4 :         aOps.insert(ocName);
     587           4 :         bool bRecompile = pCode->HasOpCodes(aOps);
     588             : 
     589           4 :         if (bRecompile)
     590             :         {
     591             :             // Get the formula string.
     592           2 :             OUString aFormula = pTop->GetFormula(mrCompileFormulaCxt);
     593           2 :             sal_Int32 n = aFormula.getLength();
     594           2 :             if (pTop->GetMatrixFlag() != MM_NONE && n > 0)
     595             :             {
     596           0 :                 if (aFormula[0] == '{' && aFormula[n-1] == '}')
     597           0 :                     aFormula = aFormula.copy(1, n-2);
     598             :             }
     599             : 
     600           2 :             if (rEntry.mbShared)
     601             :             {
     602           1 :                 ScFormulaCell** pp = rEntry.mpCells;
     603           1 :                 ScFormulaCell** ppEnd = pp + rEntry.mnLength;
     604           4 :                 for (; pp != ppEnd; ++pp)
     605             :                 {
     606           3 :                     ScFormulaCell* p = *pp;
     607           3 :                     p->EndListeningTo(mrEndListenCxt);
     608           3 :                     mpDoc->RemoveFromFormulaTree(p);
     609             :                 }
     610             :             }
     611             :             else
     612             :             {
     613           1 :                 rEntry.mpCell->EndListeningTo(mrEndListenCxt);
     614           1 :                 mpDoc->RemoveFromFormulaTree(rEntry.mpCell);
     615             :             }
     616             : 
     617           2 :             pCode->Clear();
     618           2 :             pTop->SetHybridFormula(aFormula, mpDoc->GetGrammar());
     619           4 :         }
     620           4 :     }
     621             : };
     622             : 
     623             : class PostRangeNameUpdateHandler
     624             : {
     625             :     ScDocument* mpDoc;
     626             :     sc::CompileFormulaContext& mrCompileFormulaCxt;
     627             : 
     628             : public:
     629       71680 :     PostRangeNameUpdateHandler( ScDocument* pDoc, sc::CompileFormulaContext& rCompileCxt ) :
     630             :         mpDoc(pDoc),
     631       71680 :         mrCompileFormulaCxt(rCompileCxt) {}
     632             : 
     633           4 :     void operator() ( sc::FormulaGroupEntry& rEntry )
     634             :     {
     635           4 :         if (rEntry.mbShared)
     636             :         {
     637           2 :             ScFormulaCell* pTop = *rEntry.mpCells;
     638           2 :             OUString aFormula = pTop->GetHybridFormula();
     639             : 
     640           2 :             if (!aFormula.isEmpty())
     641             :             {
     642             :                 // Create a new token array from the hybrid formula string, and
     643             :                 // set it to the group.
     644           1 :                 ScCompiler aComp(mrCompileFormulaCxt, pTop->aPos);
     645           1 :                 ScTokenArray* pNewCode = aComp.CompileString(aFormula);
     646           2 :                 ScFormulaCellGroupRef xGroup = pTop->GetCellGroup();
     647             :                 assert(xGroup);
     648           1 :                 xGroup->setCode(pNewCode);
     649           1 :                 xGroup->compileCode(*mpDoc, pTop->aPos, mpDoc->GetGrammar());
     650             : 
     651             :                 // Propagate the new token array to all formula cells in the group.
     652           1 :                 ScFormulaCell** pp = rEntry.mpCells;
     653           1 :                 ScFormulaCell** ppEnd = pp + rEntry.mnLength;
     654           4 :                 for (; pp != ppEnd; ++pp)
     655             :                 {
     656           3 :                     ScFormulaCell* p = *pp;
     657           3 :                     p->SyncSharedCode();
     658           3 :                     p->SetDirty();
     659           1 :                 }
     660           2 :             }
     661             :         }
     662             :         else
     663             :         {
     664           2 :             ScFormulaCell* pCell = rEntry.mpCell;
     665           2 :             OUString aFormula = pCell->GetHybridFormula();
     666             : 
     667           2 :             if (!aFormula.isEmpty())
     668             :             {
     669             :                 // Create token array from formula string.
     670           1 :                 ScCompiler aComp(mrCompileFormulaCxt, pCell->aPos);
     671           1 :                 ScTokenArray* pNewCode = aComp.CompileString(aFormula);
     672             : 
     673             :                 // Generate RPN tokens.
     674           2 :                 ScCompiler aComp2(mpDoc, pCell->aPos, *pNewCode);
     675           1 :                 aComp2.CompileTokenArray();
     676             : 
     677           1 :                 pCell->SetCode(pNewCode);
     678           2 :                 pCell->SetDirty();
     679           2 :             }
     680             :         }
     681           4 :     }
     682             : };
     683             : 
     684             : }
     685             : 
     686       71680 : void ScColumn::PreprocessRangeNameUpdate(
     687             :     sc::EndListeningContext& rEndListenCxt, sc::CompileFormulaContext& rCompileCxt )
     688             : {
     689             :     // Collect all formula groups.
     690       71680 :     std::vector<sc::FormulaGroupEntry> aGroups = GetFormulaGroupEntries();
     691             : 
     692       71680 :     PreRangeNameUpdateHandler aFunc(pDocument, rEndListenCxt, rCompileCxt);
     693       71680 :     std::for_each(aGroups.begin(), aGroups.end(), aFunc);
     694       71680 : }
     695             : 
     696       71680 : void ScColumn::PostprocessRangeNameUpdate( sc::CompileFormulaContext& rCompileCxt )
     697             : {
     698             :     // Collect all formula groups.
     699       71680 :     std::vector<sc::FormulaGroupEntry> aGroups = GetFormulaGroupEntries();
     700             : 
     701       71680 :     PostRangeNameUpdateHandler aFunc(pDocument, rCompileCxt);
     702       71680 :     std::for_each(aGroups.begin(), aGroups.end(), aFunc);
     703       71782 : }
     704             : 
     705             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10