LCOV - code coverage report
Current view: top level - sc/source/core/data - documentimport.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 259 318 81.4 %
Date: 2015-06-13 12:38:46 Functions: 34 40 85.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11