LCOV - code coverage report
Current view: top level - sc/source/core/data - documentimport.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 247 314 78.7 %
Date: 2014-11-03 Functions: 33 40 82.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #include "documentimport.hxx"
      11             : #include "document.hxx"
      12             : #include "table.hxx"
      13             : #include "column.hxx"
      14             : #include "formulacell.hxx"
      15             : #include "docoptio.hxx"
      16             : #include "globalnames.hxx"
      17             : #include "mtvelements.hxx"
      18             : #include "tokenarray.hxx"
      19             : #include "stringutil.hxx"
      20             : #include "compiler.hxx"
      21             : #include "paramisc.hxx"
      22             : #include "listenercontext.hxx"
      23             : #include <attarray.hxx>
      24             : 
      25             : #include <svl/sharedstringpool.hxx>
      26             : #include <svl/languageoptions.hxx>
      27             : 
      28             : #include <vector>
      29             : 
      30             : namespace {
      31             : 
      32             : struct ColAttr
      33             : {
      34             :     bool mbLatinNumFmtOnly;
      35             : 
      36       65676 :     ColAttr() : mbLatinNumFmtOnly(false) {}
      37             : };
      38             : 
      39        2308 : struct TabAttr
      40             : {
      41             :     std::vector<ColAttr> maCols;
      42             : };
      43             : 
      44             : typedef std::vector<TabAttr> TabAttrsType;
      45             : 
      46             : }
      47             : 
      48        1584 : struct ScDocumentImportImpl
      49             : {
      50             :     ScDocument& mrDoc;
      51             :     sc::StartListeningContext maListenCxt;
      52             :     sc::ColumnBlockPositionSet maBlockPosSet;
      53             :     sal_uInt16 mnDefaultScriptNumeric;
      54             : 
      55             :     TabAttrsType maTabAttrs;
      56             : 
      57        1584 :     ScDocumentImportImpl(ScDocument& rDoc) :
      58             :         mrDoc(rDoc),
      59             :         maListenCxt(rDoc),
      60             :         maBlockPosSet(rDoc),
      61        1584 :         mnDefaultScriptNumeric(SC_SCRIPTTYPE_UNKNOWN) {}
      62             : 
      63       75314 :     ColAttr* getColAttr( size_t nTab, size_t nCol )
      64             :     {
      65       75314 :         if (nTab > static_cast<size_t>(MAXTAB) || nCol > static_cast<size_t>(MAXCOL))
      66           0 :             return NULL;
      67             : 
      68       75314 :         if (nTab >= maTabAttrs.size())
      69         760 :             maTabAttrs.resize(nTab+1);
      70             : 
      71       75314 :         TabAttr& rTab = maTabAttrs[nTab];
      72       75314 :         if (nCol >= rTab.maCols.size())
      73       64614 :             rTab.maCols.resize(nCol+1);
      74             : 
      75       75314 :         return &rTab.maCols[nCol];
      76             :     }
      77             : };
      78             : 
      79       63350 : ScDocumentImport::Attrs::Attrs() : mpData(NULL), mnSize(0), mbLatinNumFmtOnly(false) {}
      80             : 
      81        1584 : ScDocumentImport::ScDocumentImport(ScDocument& rDoc) : mpImpl(new ScDocumentImportImpl(rDoc)) {}
      82        1584 : ScDocumentImport::~ScDocumentImport()
      83             : {
      84        1584 :     delete mpImpl;
      85        1584 : }
      86             : 
      87       63084 : ScDocument& ScDocumentImport::getDoc()
      88             : {
      89       63084 :     return mpImpl->mrDoc;
      90             : }
      91             : 
      92           0 : const ScDocument& ScDocumentImport::getDoc() const
      93             : {
      94           0 :     return mpImpl->mrDoc;
      95             : }
      96             : 
      97         322 : void ScDocumentImport::setDefaultNumericScript(sal_uInt16 nScript)
      98             : {
      99         322 :     mpImpl->mnDefaultScriptNumeric = nScript;
     100         322 : }
     101             : 
     102         258 : void ScDocumentImport::setCellStyleToSheet(SCTAB nTab, const ScStyleSheet& rStyle)
     103             : {
     104         258 :     ScTable* pTab = mpImpl->mrDoc.FetchTable(nTab);
     105         258 :     if (!pTab)
     106         258 :         return;
     107             : 
     108         258 :     pTab->ApplyStyleArea(0, 0, MAXCOL, MAXROW, rStyle);
     109             : }
     110             : 
     111           0 : SCTAB ScDocumentImport::getSheetIndex(const OUString& rName) const
     112             : {
     113           0 :     SCTAB nTab = -1;
     114           0 :     if (!mpImpl->mrDoc.GetTable(rName, nTab))
     115           0 :         return -1;
     116             : 
     117           0 :     return nTab;
     118             : }
     119             : 
     120           0 : SCTAB ScDocumentImport::getSheetCount() const
     121             : {
     122           0 :     return mpImpl->mrDoc.maTabs.size();
     123             : }
     124             : 
     125           0 : bool ScDocumentImport::appendSheet(const OUString& rName)
     126             : {
     127           0 :     SCTAB nTabCount = mpImpl->mrDoc.maTabs.size();
     128           0 :     if (!ValidTab(nTabCount))
     129           0 :         return false;
     130             : 
     131           0 :     mpImpl->mrDoc.maTabs.push_back(new ScTable(&mpImpl->mrDoc, nTabCount, rName));
     132           0 :     return true;
     133             : }
     134             : 
     135           0 : void ScDocumentImport::setOriginDate(sal_uInt16 nYear, sal_uInt16 nMonth, sal_uInt16 nDay)
     136             : {
     137           0 :     if (!mpImpl->mrDoc.pDocOptions)
     138           0 :         mpImpl->mrDoc.pDocOptions = new ScDocOptions;
     139             : 
     140           0 :     mpImpl->mrDoc.pDocOptions->SetDate(nDay, nMonth, nYear);
     141           0 : }
     142             : 
     143         548 : void ScDocumentImport::setAutoInput(const ScAddress& rPos, const OUString& rStr, ScSetStringParam* pStringParam)
     144             : {
     145         548 :     ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
     146         548 :     if (!pTab)
     147           0 :         return;
     148             : 
     149             :     sc::ColumnBlockPosition* pBlockPos =
     150         548 :         mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
     151             : 
     152         548 :     if (!pBlockPos)
     153           0 :         return;
     154             : 
     155         548 :     ScCellValue aCell;
     156         548 :     pTab->aCol[rPos.Col()].ParseString(
     157        1096 :         aCell, rPos.Row(), rPos.Tab(), rStr, mpImpl->mrDoc.GetAddressConvention(), pStringParam);
     158             : 
     159         548 :     sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
     160         548 :     switch (aCell.meType)
     161             :     {
     162             :         case CELLTYPE_STRING:
     163             :             // string is copied.
     164         346 :             pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), *aCell.mpString);
     165         346 :         break;
     166             :         case CELLTYPE_EDIT:
     167             :             // Cell takes the ownership of the text object.
     168           0 :             pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), aCell.mpEditText);
     169           0 :             aCell.mpEditText = NULL;
     170           0 :         break;
     171             :         case CELLTYPE_VALUE:
     172         202 :             pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), aCell.mfValue);
     173         202 :         break;
     174             :         case CELLTYPE_FORMULA:
     175             :             // This formula cell instance is directly placed in the document without copying.
     176           0 :             pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), aCell.mpFormula);
     177           0 :             aCell.mpFormula = NULL;
     178           0 :         break;
     179             :         default:
     180           0 :             pBlockPos->miCellPos = rCells.set_empty(pBlockPos->miCellPos, rPos.Row(), rPos.Row());
     181         548 :     }
     182             : }
     183             : 
     184       45834 : void ScDocumentImport::setNumericCell(const ScAddress& rPos, double fVal)
     185             : {
     186       45834 :     ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
     187       45834 :     if (!pTab)
     188           0 :         return;
     189             : 
     190             :     sc::ColumnBlockPosition* pBlockPos =
     191       45834 :         mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
     192             : 
     193       45834 :     if (!pBlockPos)
     194           0 :         return;
     195             : 
     196       45834 :     sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
     197       45834 :     pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), fVal);
     198             : }
     199             : 
     200       28286 : void ScDocumentImport::setStringCell(const ScAddress& rPos, const OUString& rStr)
     201             : {
     202       28286 :     ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
     203       28286 :     if (!pTab)
     204           0 :         return;
     205             : 
     206             :     sc::ColumnBlockPosition* pBlockPos =
     207       28286 :         mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
     208             : 
     209       28286 :     if (!pBlockPos)
     210           0 :         return;
     211             : 
     212       28286 :     svl::SharedString aSS = mpImpl->mrDoc.GetSharedStringPool().intern(rStr);
     213       28286 :     if (!aSS.getData())
     214           0 :         return;
     215             : 
     216       28286 :     sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
     217       28286 :     pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), aSS);
     218             : }
     219             : 
     220         940 : void ScDocumentImport::setEditCell(const ScAddress& rPos, EditTextObject* pEditText)
     221             : {
     222         940 :     ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
     223         940 :     if (!pTab)
     224           0 :         return;
     225             : 
     226             :     sc::ColumnBlockPosition* pBlockPos =
     227         940 :         mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
     228             : 
     229         940 :     if (!pBlockPos)
     230           0 :         return;
     231             : 
     232         940 :     pEditText->NormalizeString(mpImpl->mrDoc.GetSharedStringPool());
     233         940 :     sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
     234         940 :     pBlockPos->miCellPos = rCells.set(pBlockPos->miCellPos, rPos.Row(), pEditText);
     235             : }
     236             : 
     237           0 : void ScDocumentImport::setFormulaCell(
     238             :     const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar)
     239             : {
     240           0 :     ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
     241           0 :     if (!pTab)
     242           0 :         return;
     243             : 
     244             :     sc::ColumnBlockPosition* pBlockPos =
     245           0 :         mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
     246             : 
     247           0 :     if (!pBlockPos)
     248           0 :         return;
     249             : 
     250           0 :     sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
     251           0 :     pBlockPos->miCellPos =
     252           0 :         rCells.set(pBlockPos->miCellPos, rPos.Row(), new ScFormulaCell(&mpImpl->mrDoc, rPos, rFormula, eGrammar));
     253             : }
     254             : 
     255           0 : void ScDocumentImport::setFormulaCell(const ScAddress& rPos, ScTokenArray* pArray)
     256             : {
     257           0 :     ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
     258           0 :     if (!pTab)
     259           0 :         return;
     260             : 
     261             :     sc::ColumnBlockPosition* pBlockPos =
     262           0 :         mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
     263             : 
     264           0 :     if (!pBlockPos)
     265           0 :         return;
     266             : 
     267           0 :     sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
     268           0 :     pBlockPos->miCellPos =
     269           0 :         rCells.set(pBlockPos->miCellPos, rPos.Row(), new ScFormulaCell(&mpImpl->mrDoc, rPos, pArray));
     270             : }
     271             : 
     272       13004 : void ScDocumentImport::setFormulaCell(const ScAddress& rPos, ScFormulaCell* pCell)
     273             : {
     274       13004 :     ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
     275       13004 :     if (!pTab)
     276           0 :         return;
     277             : 
     278             :     sc::ColumnBlockPosition* pBlockPos =
     279       13004 :         mpImpl->maBlockPosSet.getBlockPosition(rPos.Tab(), rPos.Col());
     280             : 
     281       13004 :     if (!pBlockPos)
     282           0 :         return;
     283             : 
     284       13004 :     sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
     285       26008 :     pBlockPos->miCellPos =
     286       26008 :         rCells.set(pBlockPos->miCellPos, rPos.Row(), pCell);
     287             : }
     288             : 
     289          78 : void ScDocumentImport::setMatrixCells(
     290             :     const ScRange& rRange, const ScTokenArray& rArray, formula::FormulaGrammar::Grammar eGram)
     291             : {
     292          78 :     const ScAddress& rBasePos = rRange.aStart;
     293             : 
     294          78 :     ScTable* pTab = mpImpl->mrDoc.FetchTable(rBasePos.Tab());
     295          78 :     if (!pTab)
     296           0 :         return;
     297             : 
     298             :     sc::ColumnBlockPosition* pBlockPos =
     299          78 :         mpImpl->maBlockPosSet.getBlockPosition(rBasePos.Tab(), rBasePos.Col());
     300             : 
     301          78 :     if (!pBlockPos)
     302           0 :         return;
     303             : 
     304          78 :     sc::CellStoreType& rCells = pTab->aCol[rBasePos.Col()].maCells;
     305             : 
     306             :     // Set the master cell.
     307          78 :     ScFormulaCell* pCell = new ScFormulaCell(&mpImpl->mrDoc, rBasePos, rArray, eGram, MM_FORMULA);
     308             : 
     309         156 :     pBlockPos->miCellPos =
     310         156 :         rCells.set(pBlockPos->miCellPos, rBasePos.Row(), pCell);
     311             : 
     312             :     // Matrix formulas currently need re-calculation on import.
     313             :     pCell->SetMatColsRows(
     314          78 :         rRange.aEnd.Col()-rRange.aStart.Col()+1, rRange.aEnd.Row()-rRange.aStart.Row()+1, true);
     315             : 
     316             :     // Set the reference cells.
     317             :     ScSingleRefData aRefData;
     318          78 :     aRefData.InitFlags();
     319          78 :     aRefData.SetColRel(true);
     320          78 :     aRefData.SetRowRel(true);
     321          78 :     aRefData.SetTabRel(true);
     322          78 :     aRefData.SetAddress(rBasePos, rBasePos);
     323             : 
     324          78 :     ScTokenArray aArr; // consists only of one single reference token.
     325          78 :     formula::FormulaToken* t = aArr.AddMatrixSingleReference(aRefData);
     326             : 
     327          78 :     ScAddress aPos = rBasePos;
     328         160 :     for (SCROW nRow = rRange.aStart.Row()+1; nRow <= rRange.aEnd.Row(); ++nRow)
     329             :     {
     330             :         // Token array must be cloned so that each formula cell receives its own copy.
     331          82 :         aPos.SetRow(nRow);
     332             :         // Reference in each cell must point to the origin cell relative to the current cell.
     333          82 :         aRefData.SetAddress(rBasePos, aPos);
     334          82 :         *t->GetSingleRef() = aRefData;
     335          82 :         boost::scoped_ptr<ScTokenArray> pTokArr(aArr.Clone());
     336          82 :         pCell = new ScFormulaCell(&mpImpl->mrDoc, aPos, *pTokArr, eGram, MM_REFERENCE);
     337         164 :         pBlockPos->miCellPos =
     338         164 :             rCells.set(pBlockPos->miCellPos, aPos.Row(), pCell);
     339          82 :     }
     340             : 
     341         154 :     for (SCCOL nCol = rRange.aStart.Col()+1; nCol <= rRange.aEnd.Col(); ++nCol)
     342             :     {
     343          76 :         pBlockPos = mpImpl->maBlockPosSet.getBlockPosition(rBasePos.Tab(), nCol);
     344          76 :         if (!pBlockPos)
     345           0 :             return;
     346             : 
     347          76 :         sc::CellStoreType& rColCells = pTab->aCol[nCol].maCells;
     348             : 
     349          76 :         aPos.SetCol(nCol);
     350         180 :         for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
     351             :         {
     352         104 :             aPos.SetRow(nRow);
     353         104 :             aRefData.SetAddress(rBasePos, aPos);
     354         104 :             *t->GetSingleRef() = aRefData;
     355         104 :             boost::scoped_ptr<ScTokenArray> pTokArr(aArr.Clone());
     356         104 :             pCell = new ScFormulaCell(&mpImpl->mrDoc, aPos, *pTokArr, eGram, MM_REFERENCE);
     357         208 :             pBlockPos->miCellPos =
     358         208 :                 rColCells.set(pBlockPos->miCellPos, aPos.Row(), pCell);
     359         104 :         }
     360          78 :     }
     361             : }
     362             : 
     363          10 : void ScDocumentImport::setTableOpCells(const ScRange& rRange, const ScTabOpParam& rParam)
     364             : {
     365          10 :     SCTAB nTab = rRange.aStart.Tab();
     366          10 :     SCCOL nCol1 = rRange.aStart.Col();
     367          10 :     SCROW nRow1 = rRange.aStart.Row();
     368          10 :     SCCOL nCol2 = rRange.aEnd.Col();
     369          10 :     SCROW nRow2 = rRange.aEnd.Row();
     370             : 
     371          10 :     ScTable* pTab = mpImpl->mrDoc.FetchTable(nTab);
     372          10 :     if (!pTab)
     373           0 :         return;
     374             : 
     375          10 :     ScDocument* pDoc = &mpImpl->mrDoc;
     376          10 :     ScRefAddress aRef;
     377          10 :     OUStringBuffer aFormulaBuf('=');
     378          10 :     aFormulaBuf.append(ScCompiler::GetNativeSymbol(ocTableOp));
     379          10 :     aFormulaBuf.append(ScCompiler::GetNativeSymbol(ocOpen));
     380             : 
     381          20 :     OUString aSep = ScCompiler::GetNativeSymbol(ocSep);
     382          10 :     if (rParam.meMode == ScTabOpParam::Column) // column only
     383             :     {
     384           4 :         aRef.Set(rParam.aRefFormulaCell.GetAddress(), true, false, false);
     385           4 :         aFormulaBuf.append(aRef.GetRefString(pDoc, nTab));
     386           4 :         aFormulaBuf.append(aSep);
     387           4 :         aFormulaBuf.append(rParam.aRefColCell.GetRefString(pDoc, nTab));
     388           4 :         aFormulaBuf.append(aSep);
     389           4 :         aRef.Set(nCol1, nRow1, nTab, false, true, true);
     390           4 :         aFormulaBuf.append(aRef.GetRefString(pDoc, nTab));
     391           4 :         nCol1++;
     392           4 :         nCol2 = std::min( nCol2, (SCCOL)(rParam.aRefFormulaEnd.Col() -
     393           4 :                     rParam.aRefFormulaCell.Col() + nCol1 + 1));
     394             :     }
     395           6 :     else if (rParam.meMode == ScTabOpParam::Row) // row only
     396             :     {
     397           2 :         aRef.Set(rParam.aRefFormulaCell.GetAddress(), false, true, false);
     398           2 :         aFormulaBuf.append(aRef.GetRefString(pDoc, nTab));
     399           2 :         aFormulaBuf.append(aSep);
     400           2 :         aFormulaBuf.append(rParam.aRefRowCell.GetRefString(pDoc, nTab));
     401           2 :         aFormulaBuf.append(aSep);
     402           2 :         aRef.Set(nCol1, nRow1, nTab, true, false, true);
     403           2 :         aFormulaBuf.append(aRef.GetRefString(pDoc, nTab));
     404           2 :         ++nRow1;
     405             :         nRow2 = std::min(
     406           2 :             nRow2, rParam.aRefFormulaEnd.Row() - rParam.aRefFormulaCell.Row() + nRow1 + 1);
     407             :     }
     408             :     else // both
     409             :     {
     410           4 :         aFormulaBuf.append(rParam.aRefFormulaCell.GetRefString(pDoc, nTab));
     411           4 :         aFormulaBuf.append(aSep);
     412           4 :         aFormulaBuf.append(rParam.aRefColCell.GetRefString(pDoc, nTab));
     413           4 :         aFormulaBuf.append(aSep);
     414           4 :         aRef.Set(nCol1, nRow1 + 1, nTab, false, true, true);
     415           4 :         aFormulaBuf.append(aRef.GetRefString(pDoc, nTab));
     416           4 :         aFormulaBuf.append(aSep);
     417           4 :         aFormulaBuf.append(rParam.aRefRowCell.GetRefString(pDoc, nTab));
     418           4 :         aFormulaBuf.append(aSep);
     419           4 :         aRef.Set(nCol1 + 1, nRow1, nTab, true, false, true);
     420           4 :         aFormulaBuf.append(aRef.GetRefString(pDoc, nTab));
     421           4 :         ++nCol1;
     422           4 :         ++nRow1;
     423             :     }
     424             : 
     425          10 :     aFormulaBuf.append(ScCompiler::GetNativeSymbol(ocClose));
     426             : 
     427             :     ScFormulaCell aRefCell(
     428             :         pDoc, ScAddress(nCol1, nRow1, nTab), aFormulaBuf.makeStringAndClear(),
     429          20 :         formula::FormulaGrammar::GRAM_NATIVE, MM_NONE);
     430             : 
     431          52 :     for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
     432             :     {
     433             :         sc::ColumnBlockPosition* pBlockPos =
     434          42 :             mpImpl->maBlockPosSet.getBlockPosition(nTab, nCol);
     435             : 
     436          42 :         if (!pBlockPos)
     437             :             // Something went horribly wrong.
     438           0 :             return;
     439             : 
     440          42 :         sc::CellStoreType& rColCells = pTab->aCol[nCol].maCells;
     441             : 
     442         372 :         for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
     443             :         {
     444         330 :             ScAddress aPos(nCol, nRow, nTab);
     445         330 :             ScFormulaCell* pCell = new ScFormulaCell(aRefCell, *pDoc, aPos);
     446         660 :             pBlockPos->miCellPos =
     447         330 :                 rColCells.set(pBlockPos->miCellPos, nRow, pCell);
     448             :         }
     449          10 :     }
     450             : }
     451             : 
     452       63350 : void ScDocumentImport::setAttrEntries( SCTAB nTab, SCCOL nCol, Attrs& rAttrs )
     453             : {
     454       63350 :     ScTable* pTab = mpImpl->mrDoc.FetchTable(nTab);
     455       63350 :     if (!pTab)
     456           0 :         return;
     457             : 
     458       63350 :     ScColumn* pCol = pTab->FetchColumn(nCol);
     459       63350 :     if (!pCol)
     460           0 :         return;
     461             : 
     462       63350 :     ColAttr* pColAttr = mpImpl->getColAttr(nTab, nCol);
     463       63350 :     if (pColAttr)
     464       63350 :         pColAttr->mbLatinNumFmtOnly = rAttrs.mbLatinNumFmtOnly;
     465             : 
     466       63350 :     pCol->pAttrArray->SetAttrEntries(rAttrs.mpData, rAttrs.mnSize);
     467             : }
     468             : 
     469             : namespace {
     470             : 
     471     6481920 : class CellStoreInitializer
     472             : {
     473             :     // The pimpl pattern here is intentional.
     474             :     //
     475             :     // The problem with having the attributes in CellStoreInitializer
     476             :     // directly is that, as a functor, it might be copied around. In
     477             :     // that case miPos in _copied_ object points ot maAttrs in the
     478             :     // original object, not in the copy. So later, deep in mdds, we end
     479             :     // up comparing iterators from different sequences.
     480             :     //
     481             :     // This could be solved by defining copy constructor and operator=,
     482             :     // but given the limited usage of the class, I think it is simpler
     483             :     // to let copies share the state.
     484     1296384 :     struct Impl
     485             :     {
     486             :         sc::CellTextAttrStoreType maAttrs;
     487             :         sc::CellTextAttrStoreType::iterator miPos;
     488             :         sal_uInt16 mnScriptNumeric;
     489             : 
     490     1296384 :         Impl(const sal_uInt32 nMaxRowCount, const sal_uInt16 nScriptNumeric)
     491     1296384 :             : maAttrs(nMaxRowCount), miPos(maAttrs.begin()), mnScriptNumeric(nScriptNumeric)
     492     1296384 :         {}
     493             :     };
     494             : 
     495             :     ScDocumentImportImpl& mrDocImpl;
     496             :     SCTAB mnTab;
     497             :     SCCOL mnCol;
     498             : 
     499             : public:
     500     1296384 :     CellStoreInitializer( ScDocumentImportImpl& rDocImpl, SCTAB nTab, SCCOL nCol ) :
     501             :         mrDocImpl(rDocImpl),
     502             :         mnTab(nTab),
     503             :         mnCol(nCol),
     504     1296384 :         mpImpl(new Impl(MAXROWCOUNT, mrDocImpl.mnDefaultScriptNumeric))
     505     1296384 :     {}
     506             : 
     507             :     boost::shared_ptr<Impl> mpImpl;
     508             : 
     509     1329670 :     void operator() (const sc::CellStoreType::value_type& node)
     510             :     {
     511     1329670 :         if (node.type == sc::element_type_empty)
     512     2639696 :             return;
     513             : 
     514             :         // Fill with default values for non-empty cell segments.
     515       19644 :         sc::CellTextAttr aDefault;
     516       19644 :         switch (node.type)
     517             :         {
     518             :             case sc::element_type_numeric:
     519             :             {
     520        8862 :                 aDefault.mnScriptType = mpImpl->mnScriptNumeric;
     521        8862 :                 const ColAttr* p = mrDocImpl.getColAttr(mnTab, mnCol);
     522        8862 :                 if (p && p->mbLatinNumFmtOnly)
     523         442 :                     aDefault.mnScriptType = SCRIPTTYPE_LATIN;
     524             :             }
     525        8862 :             break;
     526             :             case sc::element_type_formula:
     527             :             {
     528        3102 :                 const ColAttr* p = mrDocImpl.getColAttr(mnTab, mnCol);
     529        3102 :                 if (p && p->mbLatinNumFmtOnly)
     530             :                 {
     531             :                     // We can assume latin script type if the block only
     532             :                     // contains formula cells with numeric results.
     533         248 :                     ScFormulaCell** pp = &sc::formula_block::at(*node.data, 0);
     534         248 :                     ScFormulaCell** ppEnd = pp + node.size;
     535         248 :                     bool bNumResOnly = true;
     536        1394 :                     for (; pp != ppEnd; ++pp)
     537             :                     {
     538        1240 :                         const ScFormulaCell& rCell = **pp;
     539        1240 :                         if (!rCell.IsValueNoError())
     540             :                         {
     541          94 :                             bNumResOnly = false;
     542          94 :                             break;
     543             :                         }
     544             :                     }
     545             : 
     546         248 :                     if (bNumResOnly)
     547         154 :                         aDefault.mnScriptType = SCRIPTTYPE_LATIN;
     548             :                 }
     549             :             }
     550        3102 :             break;
     551             :             default:
     552             :                 ;
     553             :         }
     554             : 
     555       19644 :         std::vector<sc::CellTextAttr> aDefaults(node.size, aDefault);
     556       19644 :         mpImpl->miPos = mpImpl->maAttrs.set(mpImpl->miPos, node.position, aDefaults.begin(), aDefaults.end());
     557             : 
     558       19644 :         if (node.type == sc::element_type_formula)
     559             :         {
     560             :             // Have all formula cells start listening to the document.
     561        3102 :             sc::formula_block::iterator it = sc::formula_block::begin(*node.data);
     562        3102 :             sc::formula_block::iterator itEnd = sc::formula_block::end(*node.data);
     563       16702 :             for (; it != itEnd; ++it)
     564             :             {
     565       13600 :                 ScFormulaCell& rFC = **it;
     566       13600 :                 rFC.StartListeningTo(mrDocImpl.maListenCxt);
     567             :             }
     568       19644 :         }
     569             :     }
     570             : 
     571     1296384 :     void swap(sc::CellTextAttrStoreType& rAttrs)
     572             :     {
     573     1296384 :         mpImpl->maAttrs.swap(rAttrs);
     574     1296384 :     }
     575             : };
     576             : 
     577             : }
     578             : 
     579         600 : void ScDocumentImport::finalize()
     580             : {
     581             :     // Populate the text width and script type arrays in all columns. Also
     582             :     // activate all formula cells.
     583         600 :     ScDocument::TableContainer::iterator itTab = mpImpl->mrDoc.maTabs.begin(), itTabEnd = mpImpl->mrDoc.maTabs.end();
     584        1866 :     for (; itTab != itTabEnd; ++itTab)
     585             :     {
     586        1266 :         if (!*itTab)
     587           0 :             continue;
     588             : 
     589        1266 :         ScTable& rTab = **itTab;
     590        1266 :         ScColumn* pCol = &rTab.aCol[0];
     591        1266 :         ScColumn* pColEnd = pCol + static_cast<size_t>(MAXCOLCOUNT);
     592     1297650 :         for (; pCol != pColEnd; ++pCol)
     593     1296384 :             initColumn(*pCol);
     594             :     }
     595         600 : }
     596             : 
     597     1296384 : void ScDocumentImport::initColumn(ScColumn& rCol)
     598             : {
     599     1296384 :     CellStoreInitializer aFunc(*mpImpl, rCol.nTab, rCol.nCol);
     600     1296384 :     std::for_each(rCol.maCells.begin(), rCol.maCells.end(), aFunc);
     601     1296384 :     aFunc.swap(rCol.maCellTextAttrs);
     602     1296384 :     rCol.RegroupFormulaCells();
     603     1296384 :     rCol.CellStorageModified();
     604     1296612 : }
     605             : 
     606             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10