[Libreoffice-commits] core.git: Branch 'private/kohei/xlsx-import-speedup' - 170 commits - animations/source avmedia/source basegfx/source bin/fixincludeguards.sh bin/update_pch.sh bluez_bluetooth/inc bluez_bluetooth/README bridges/Library_cpp_uno.mk bridges/Module_bridges.mk canvas/source chart2/inc codemaker/source config_host.mk.in configure.ac connectivity/source cui/inc cui/source dbaccess/inc dbaccess/source desktop/source download.lst drawinglayer/source editeng/source extensions/source external/accessories external/bluez_bluetooth external/hyphen external/libxmlsec external/mingw-externals external/Module_external.mk external/mythes external/nss external/openssl external/postgresql external/sane external/twain external/unixODBC extras/AllLangPackage_accessoriessamplesadvertisement.mk extras/AllLangPackage_accessoriessamplesdocumentation.mk extras/AllLangPackage_accessoriessamples.mk extras/AllLangPackage_accessoriessamplesnonfreeadvertisement.mk extras/AllLangPackage_accessoriessa mplesnonfreedocumentation.mk extras/AllLangPackage_accessoriessamplesnonfree.mk extras/AllLangPackage_accessoriestemplateseducate.mk extras/AllLangPackage_accessoriestemplatesfinance.mk extras/AllLangPackage_accessoriestemplatesforms.mk extras/AllLangPackage_accessoriestemplateslabels.mk extras/AllLangPackage_accessoriestemplateslayout.mk extras/AllLangPackage_accessoriestemplatesmisc.mk extras/AllLangPackage_accessoriestemplates.mk extras/AllLangPackage_accessoriestemplatesnonfreeeducate.mk extras/AllLangPackage_accessoriestemplatesnonfreefinance.mk extras/AllLangPackage_accessoriestemplatesnonfreeforms.mk extras/AllLangPackage_accessoriestemplatesnonfreelabels.mk extras/AllLangPackage_accessoriestemplatesnonfreelayout.mk extras/AllLangPackage_accessoriestemplatesnonfreemisc.mk extras/AllLangPackage_accessoriestemplatesnonfree.mk extras/AllLangPackage_accessoriestemplatesnonfreeofficorr.mk extras/AllLangPackage_accessoriestemplatesnonfreeoffimisc.mk extras/AllLangPackage_ac cessoriestemplatesnonfreepersonal.mk extras/AllLangPackage_accessoriestemplatesnonfreepresent.mk extras/AllLangPackage_accessoriestemplatesofficorr.mk extras/AllLangPackage_accessoriestemplatesoffimisc.mk extras/AllLangPackage_accessoriestemplatespersonal.mk extras/AllLangPackage_accessoriestemplatespresent.mk extras/ExternalPackage_accessoriesgallerydrawspeople.mk extras/ExternalPackage_accessoriesgalleryelementsbullets2.mk extras/ExternalPackage_accessoriesgallery.mk extras/ExternalPackage_accessoriesgallerynonfree.mk extras/ExternalPackage_accessoriesgalleryphotosbuildings.mk extras/ExternalPackage_accessoriesgalleryphotoscelebration.mk extras/ExternalPackage_accessoriesgalleryphotoscities.mk extras/ExternalPackage_accessoriesgalleryphotosfauna.mk extras/ExternalPackage_accessoriesgalleryphotosflowers.mk extras/ExternalPackage_accessoriesgalleryphotosfoodsanddrinks.mk extras/ExternalPackage_accessoriesgalleryphotoshumans.mk extras/ExternalPackage_accessoriesgalleryphotosl andscapes.mk extras/ExternalPackage_accessoriesgalleryphotosobjects.mk extras/ExternalPackage_accessoriesgalleryphotosplants.mk extras/ExternalPackage_accessoriesgalleryphotosspace.mk extras/ExternalPackage_accessoriesgalleryphotosstatues.mk extras/ExternalPackage_accessoriesgalleryphotostravel.mk extras/ExternalPackage_accessoriestemplatescommoneducate.mk extras/ExternalPackage_accessoriestemplatescommonfinance.mk extras/ExternalPackage_accessoriestemplatescommonforms.mk extras/ExternalPackage_accessoriestemplatescommonlabels.mk extras/ExternalPackage_accessoriestemplatescommonlayout.mk extras/ExternalPackage_accessoriestemplatescommonmisc.mk extras/ExternalPackage_accessoriestemplatescommon.mk extras/ExternalPackage_accessoriestemplatescommonofficorr.mk extras/ExternalPackage_accessoriestemplatescommonoffimisc.mk extras/ExternalPackage_accessoriestemplatescommonpersonal.mk extras/ExternalPackage_accessoriestemplatescommonpresent.mk extras/ExternalPackage_extra_fonts.mk ext ras/Module_extras.mk extras/UnpackedTarball_fonts_pack.mk extras/UnpackedTarball_gallery_pack.mk extras/UnpackedTarball_samples_pack.mk extras/UnpackedTarball_templates_pack.mk filter/source forms/source formula/source framework/inc framework/source helpcontent2 i18nlangtag/source i18npool/Library_localedata_euro.mk i18npool/source idl/inc idl/source include/basegfx include/drawinglayer include/editeng include/formula include/i18nlangtag include/linguistic include/rtl include/svl include/svx include/tools io/Library_acceptor.mk io/Library_connector.mk io/Library_io.mk io/Library_streams.mk io/Library_textinstream.mk io/Library_textoutstream.mk io/Module_io.mk ios/CustomTarget_LibreOffice_app.mk ios/experimental io/source l10ntools/inc libxmlsec/ExternalPackage_xmlsec.mk libxmlsec/ExternalProject_xmlsec.mk libxmlsec/include libxmlsec/Makefile libxmlsec/Module_libxmlsec.mk libxmlsec/README libxmlsec/src libxmlsec/UnpackedTarball_xmlsec.mk libxmlsec/xmlsec1-1.2.14-ansi.patch li bxmlsec/xmlsec1-1.2.14_fix_extern_c.patch libxmlsec/xmlsec1-android.patch libxmlsec/xmlsec1-configure-libxml-libxslt.patch libxmlsec/xmlsec1-configure.patch libxmlsec/xmlsec1-customkeymanage.patch libxmlsec/xmlsec1-mingw32.patch libxmlsec/xmlsec1-mingw-keymgr-mscrypto.patch libxmlsec/xmlsec1-noverify.patch libxmlsec/xmlsec1-nssdisablecallbacks.patch libxmlsec/xmlsec1-nssmangleciphers.patch libxmlsec/xmlsec1-olderlibxml2.patch libxmlsec/xmlsec1-oldlibtool.patch libxmlsec/xmlsec1-vc.patch linguistic/inc linguistic/source linguistic/workben lotuswordpro/source odk/CustomTarget_check.mk offapi/com oox/inc oox/source reportdesign/source RepositoryExternal.mk Repository.mk RepositoryModule_host.mk sal/cpprt sal/Library_sal.mk sane/inc sane/README sc/inc sc/Library_scopencl.mk scp2/source sc/qa scripting/source sc/source sd/AllLangResTarget_sd.mk sd/CppunitTest_sd_import_tests.mk sdext/source sd/inc sd/Library_sd.mk sd/qa sd/source sd/uiconfig sd/UIConfig_simpress.mk sfx2/inc sfx2/ source shell/Executable_lngconvex.mk shell/inc shell/Library_ooofilt.mk shell/Library_ooofilt_x64.mk shell/Library_propertyhdl.mk shell/Library_propertyhdl_x64.mk shell/Library_shlxthdl.mk shell/Library_shlxthdl_x64.mk shell/source shell/StaticLibrary_shlxthandler_common.mk shell/StaticLibrary_shlxthandler_common_x64.mk solenv/bin solenv/gbuild starmath/inc starmath/source svgio/source svl/source svtools/inc svtools/source svx/inc svx/source sw/inc sw/qa sw/source twain/inc twain/README unixODBC/inc unixODBC/README unodevtools/inc unodevtools/source unoidl/source unotest/source unoxml/source ure/Rdb_ure.mk vcl/generic vcl/inc vcl/Library_vcl.mk vcl/source vcl/unx vcl/win writerfilter/inc writerfilter/source xmloff/inc xmloff/source

Kohei Yoshida kohei.yoshida at collabora.com
Thu Nov 7 02:41:55 CET 2013


Rebased ref, commits from common ancestor:
commit db65fff2aa0e98622932c0372212b4a68f65b72e
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Nov 6 18:51:34 2013 -0500

    Perform formula cell compilations in multiple threads during xlsx import.
    
    One sheet per thread. Right now the thread count is set to 1 due to non
    re-entrancy of a large portion of Calc core, and beyond. We need to fix
    that first before setting the thread count to more than 1.
    
    Change-Id: I6997c1e9540de939f1f00b1798e2b32059787ae5

diff --git a/sc/source/filter/inc/formulabuffer.hxx b/sc/source/filter/inc/formulabuffer.hxx
index f9e5229..7e881ee 100644
--- a/sc/source/filter/inc/formulabuffer.hxx
+++ b/sc/source/filter/inc/formulabuffer.hxx
@@ -13,6 +13,8 @@
 #include <utility>
 #include "oox/helper/refmap.hxx"
 #include "oox/helper/refvector.hxx"
+#include "salhelper/thread.hxx"
+#include "osl/mutex.hxx"
 #include "workbookhelper.hxx"
 #include <com/sun/star/table/CellAddress.hpp>
 #include <com/sun/star/table/CellRangeAddress.hpp>
@@ -29,6 +31,21 @@ namespace oox { namespace xls {
 
 class FormulaBuffer : public WorkbookHelper
 {
+    class FinalizeThread : public salhelper::Thread
+    {
+        FormulaBuffer& mrParent;
+        size_t mnThreadCount;
+    public:
+        FinalizeThread( FormulaBuffer& rParent, size_t nThreadCount );
+        virtual ~FinalizeThread();
+
+    protected:
+        virtual void execute();
+    };
+
+    friend class FinalizeThread;
+
+public:
     /**
      * Represents a shared formula definition.
      */
@@ -74,6 +91,20 @@ class FormulaBuffer : public WorkbookHelper
         TokenRangeAddressItem( const TokenAddressItem& rTokenAndAddress, const ::com::sun::star::table::CellRangeAddress& rCellRangeAddress ) : maTokenAndAddress( rTokenAndAddress ), maCellRangeAddress( rCellRangeAddress ) {}
     };
 
+    typedef std::pair<com::sun::star::table::CellAddress, double> ValueAddressPair;
+
+    struct SheetItem
+    {
+        std::vector<TokenAddressItem>* mpCellFormulas;
+        std::vector<TokenRangeAddressItem>* mpArrayFormulas;
+        std::vector<ValueAddressPair>* mpCellFormulaValues;
+        std::vector<SharedFormulaEntry>* mpSharedFormulaEntries;
+        std::vector<SharedFormulaDesc>* mpSharedFormulaIDs;
+
+        SheetItem();
+    };
+
+private:
     typedef ::std::map< SCTAB, std::vector<TokenAddressItem> > FormulaDataMap;
     typedef ::std::map< SCTAB, std::vector<TokenRangeAddressItem> > ArrayFormulaDataMap;
     // sheet -> list of shared formula descriptions
@@ -81,19 +112,16 @@ class FormulaBuffer : public WorkbookHelper
     // sheet -> stuff needed to create shared formulae
     typedef ::std::map< SCTAB, std::vector<SharedFormulaEntry> >  SheetToFormulaEntryMap;
 
-    typedef ::std::pair< ::com::sun::star::table::CellAddress, double > ValueAddressPair;
     typedef ::std::map< SCTAB, std::vector<ValueAddressPair> > FormulaValueMap;
 
+    osl::Mutex maMtxData;
     FormulaDataMap maCellFormulas;
     ArrayFormulaDataMap maCellArrayFormulas;
     SheetToFormulaEntryMap maSharedFormulas;
     SheetToSharedFormulaid maSharedFormulaIds;
     FormulaValueMap maCellFormulaValues;
 
-    void                applyArrayFormulas(  const std::vector< TokenRangeAddressItem >& rVector );
-    void                applyCellFormulas(  const std::vector< TokenAddressItem >& rVector );
-    void                applyCellFormulaValues( const std::vector< ValueAddressPair >& rVector );
-    void applySharedFormulas( SCTAB nTab );
+    SheetItem getSheetItem( SCTAB nTab );
 
 public:
     explicit            FormulaBuffer( const WorkbookHelper& rHelper );
diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx
index 04be139..c3e1d24 100644
--- a/sc/source/filter/oox/formulabuffer.cxx
+++ b/sc/source/filter/oox/formulabuffer.cxx
@@ -33,114 +33,22 @@ using namespace ::com::sun::star::table;
 using namespace ::com::sun::star::sheet;
 using namespace ::com::sun::star::container;
 
-namespace oox { namespace xls {
-
-FormulaBuffer::SharedFormulaEntry::SharedFormulaEntry(
-    const table::CellAddress& rAddr, const table::CellRangeAddress& rRange,
-    const OUString& rTokenStr, sal_Int32 nSharedId ) :
-    maAddress(rAddr), maRange(rRange), maTokenStr(rTokenStr), mnSharedId(nSharedId) {}
-
-FormulaBuffer::SharedFormulaDesc::SharedFormulaDesc(
-    const com::sun::star::table::CellAddress& rAddr, sal_Int32 nSharedId,
-    const OUString& rCellValue, sal_Int32 nValueType ) :
-    maAddress(rAddr), mnSharedId(nSharedId), maCellValue(rCellValue), mnValueType(nValueType) {}
-
-FormulaBuffer::FormulaBuffer( const WorkbookHelper& rHelper ) : WorkbookHelper( rHelper )
-{
-}
-
-void FormulaBuffer::finalizeImport()
-{
-    ISegmentProgressBarRef xFormulaBar = getProgressBar().createSegment( getProgressBar().getFreeLength() );
-
-    ScDocument& rDoc = getScDocument();
-    rDoc.SetAutoNameCache( new ScAutoNameCache( &rDoc ) );
-    for (SCTAB nTab = 0, nElem = rDoc.GetTableCount(); nTab < nElem; ++nTab)
-    {
-        double fPosition = static_cast< double> (nTab + 1) /static_cast<double>(nElem);
-        xFormulaBar->setPosition( fPosition );
+#include <boost/scoped_ptr.hpp>
 
-        applySharedFormulas(nTab);
-
-        FormulaDataMap::iterator cellIt = maCellFormulas.find( nTab );
-        if ( cellIt != maCellFormulas.end() )
-        {
-            applyCellFormulas( cellIt->second );
-        }
-
-        ArrayFormulaDataMap::iterator itArray = maCellArrayFormulas.find( nTab );
-        if ( itArray != maCellArrayFormulas.end() )
-        {
-            applyArrayFormulas( itArray->second );
-        }
-
-        FormulaValueMap::iterator itValues = maCellFormulaValues.find( nTab );
-        if ( itValues != maCellFormulaValues.end() )
-        {
-            std::vector< ValueAddressPair > & rVector = itValues->second;
-            applyCellFormulaValues( rVector );
-        }
-    }
-    rDoc.SetAutoNameCache( NULL );
-    xFormulaBar->setPosition( 1.0 );
-}
-
-void FormulaBuffer::applyCellFormulas( const std::vector< TokenAddressItem >& rVector )
-{
-    ScDocumentImport& rDoc = getDocImport();
-    ScExternalRefManager::ApiGuard aExtRefGuard(&rDoc.getDoc());
-    for ( std::vector< TokenAddressItem >::const_iterator it = rVector.begin(), it_end = rVector.end(); it != it_end; ++it )
-    {
-        ScAddress aPos;
-        ScUnoConversion::FillScAddress(aPos, it->maCellAddress);
-        ScCompiler aCompiler(&rDoc.getDoc(), aPos);
-        aCompiler.SetGrammar(formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX);
-        ScTokenArray* pCode = aCompiler.CompileString(it->maTokenStr);
-        if (!pCode)
-            continue;
+namespace oox { namespace xls {
 
-        rDoc.setFormulaCell(aPos, pCode);
-    }
-}
+namespace {
 
-void FormulaBuffer::applyCellFormulaValues( const std::vector< ValueAddressPair >& rVector )
+void applySharedFormulas(
+    ScDocumentImport& rDoc,
+    SvNumberFormatter& rFormatter,
+    std::vector<FormulaBuffer::SharedFormulaEntry>& rSharedFormulas,
+    std::vector<FormulaBuffer::SharedFormulaDesc>& rCells )
 {
-    ScDocument& rDoc = getScDocument();
-    for ( std::vector< ValueAddressPair >::const_iterator it = rVector.begin(), it_end = rVector.end(); it != it_end; ++it )
-    {
-        ScAddress aCellPos;
-        ScUnoConversion::FillScAddress( aCellPos, it->first );
-        ScFormulaCell* pCell = rDoc.GetFormulaCell(aCellPos);
-        if (pCell)
-        {
-            pCell->SetHybridDouble( it->second );
-            pCell->ResetDirty();
-            pCell->SetChanged(false);
-        }
-    }
-}
-
-void FormulaBuffer::applySharedFormulas( SCTAB nTab )
-{
-    SheetToFormulaEntryMap::const_iterator itShared = maSharedFormulas.find(nTab);
-    if (itShared == maSharedFormulas.end())
-        // There is no shared formulas for this sheet.
-        return;
-
-    SheetToSharedFormulaid::const_iterator itCells = maSharedFormulaIds.find(nTab);
-    if (itCells == maSharedFormulaIds.end())
-        // There is no formula cells that use shared formulas for this sheet.
-        return;
-
-    const std::vector<SharedFormulaEntry>& rSharedFormulas = itShared->second;
-    const std::vector<SharedFormulaDesc>& rCells = itCells->second;
-
-    ScDocumentImport& rDoc = getDocImport();
-
     sc::SharedFormulaGroups aGroups;
     {
         // Process shared formulas first.
-        std::vector<SharedFormulaEntry>::const_iterator it = rSharedFormulas.begin(), itEnd = rSharedFormulas.end();
+        std::vector<FormulaBuffer::SharedFormulaEntry>::const_iterator it = rSharedFormulas.begin(), itEnd = rSharedFormulas.end();
         for (; it != itEnd; ++it)
         {
             const table::CellAddress& rAddr = it->maAddress;
@@ -150,6 +58,7 @@ void FormulaBuffer::applySharedFormulas( SCTAB nTab )
             ScAddress aPos;
             ScUnoConversion::FillScAddress(aPos, rAddr);
             ScCompiler aComp(&rDoc.getDoc(), aPos);
+            aComp.SetNumberFormatter(&rFormatter);
             aComp.SetGrammar(formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX);
             ScTokenArray* pArray = aComp.CompileString(rTokenStr);
             if (pArray)
@@ -159,7 +68,7 @@ void FormulaBuffer::applySharedFormulas( SCTAB nTab )
 
     {
         // Process formulas that use shared formulas.
-        std::vector<SharedFormulaDesc>::const_iterator it = rCells.begin(), itEnd = rCells.end();
+        std::vector<FormulaBuffer::SharedFormulaDesc>::const_iterator it = rCells.begin(), itEnd = rCells.end();
         for (; it != itEnd; ++it)
         {
             const table::CellAddress& rAddr = it->maAddress;
@@ -194,10 +103,32 @@ void FormulaBuffer::applySharedFormulas( SCTAB nTab )
     }
 }
 
-void FormulaBuffer::applyArrayFormulas( const std::vector< TokenRangeAddressItem >& rVector )
+void applyCellFormulas(
+    ScDocumentImport& rDoc, SvNumberFormatter& rFormatter,
+    const std::vector<FormulaBuffer::TokenAddressItem>& rCells )
 {
-    ScDocumentImport& rDocImport = getDocImport();
-    std::vector<TokenRangeAddressItem>::const_iterator it = rVector.begin(), itEnd = rVector.end();
+    ScExternalRefManager::ApiGuard aExtRefGuard(&rDoc.getDoc());
+    std::vector<FormulaBuffer::TokenAddressItem>::const_iterator it = rCells.begin(), itEnd = rCells.end();
+    for (; it != itEnd; ++it)
+    {
+        ScAddress aPos;
+        ScUnoConversion::FillScAddress(aPos, it->maCellAddress);
+        ScCompiler aCompiler(&rDoc.getDoc(), aPos);
+        aCompiler.SetNumberFormatter(&rFormatter);
+        aCompiler.SetGrammar(formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX);
+        ScTokenArray* pCode = aCompiler.CompileString(it->maTokenStr);
+        if (!pCode)
+            continue;
+
+        rDoc.setFormulaCell(aPos, pCode);
+    }
+}
+
+void applyArrayFormulas(
+    ScDocumentImport& rDoc, SvNumberFormatter& rFormatter,
+    const std::vector<FormulaBuffer::TokenRangeAddressItem>& rArrays )
+{
+    std::vector<FormulaBuffer::TokenRangeAddressItem>::const_iterator it = rArrays.begin(), itEnd = rArrays.end();
     for (; it != itEnd; ++it)
     {
         ScAddress aPos;
@@ -205,12 +136,185 @@ void FormulaBuffer::applyArrayFormulas( const std::vector< TokenRangeAddressItem
         ScRange aRange;
         ScUnoConversion::FillScRange(aRange, it->maCellRangeAddress);
 
-        ScCompiler aComp(&rDocImport.getDoc(), aPos);
+        ScCompiler aComp(&rDoc.getDoc(), aPos);
+        aComp.SetNumberFormatter(&rFormatter);
         aComp.SetGrammar(formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX);
         boost::scoped_ptr<ScTokenArray> pArray(aComp.CompileString(it->maTokenAndAddress.maTokenStr));
         if (pArray)
-            rDocImport.setMatrixCells(aRange, *pArray, formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX);
+            rDoc.setMatrixCells(aRange, *pArray, formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX);
+    }
+}
+
+void applyCellFormulaValues(
+    ScDocumentImport& rDoc, const std::vector<FormulaBuffer::ValueAddressPair>& rVector )
+{
+    std::vector<FormulaBuffer::ValueAddressPair>::const_iterator it = rVector.begin(), itEnd = rVector.end();
+    for (; it != itEnd; ++it)
+    {
+        ScAddress aCellPos;
+        ScUnoConversion::FillScAddress(aCellPos, it->first);
+        ScFormulaCell* pCell = rDoc.getDoc().GetFormulaCell(aCellPos);
+        if (pCell)
+        {
+            pCell->SetHybridDouble(it->second);
+            pCell->ResetDirty();
+            pCell->SetChanged(false);
+        }
+    }
+}
+
+class WorkerThread : public salhelper::Thread
+{
+    ScDocumentImport& mrDoc;
+    FormulaBuffer::SheetItem& mrItem;
+    boost::scoped_ptr<SvNumberFormatter> mpFormatter;
+
+    WorkerThread( const WorkerThread& );
+    WorkerThread& operator= ( const WorkerThread& );
+
+public:
+    WorkerThread( ScDocumentImport& rDoc, FormulaBuffer::SheetItem& rItem, SvNumberFormatter* pFormatter ) :
+        salhelper::Thread("xlsx-import-formula-buffer-worker-thread"),
+        mrDoc(rDoc), mrItem(rItem), mpFormatter(pFormatter) {}
+
+    virtual ~WorkerThread() {}
+
+protected:
+    virtual void execute()
+    {
+        if (mrItem.mpSharedFormulaEntries && mrItem.mpSharedFormulaIDs)
+            applySharedFormulas(mrDoc, *mpFormatter, *mrItem.mpSharedFormulaEntries, *mrItem.mpSharedFormulaIDs);
+
+        if (mrItem.mpCellFormulas)
+            applyCellFormulas(mrDoc, *mpFormatter, *mrItem.mpCellFormulas);
+
+        if (mrItem.mpArrayFormulas)
+            applyArrayFormulas(mrDoc, *mpFormatter, *mrItem.mpArrayFormulas);
+
+        if (mrItem.mpCellFormulaValues)
+            applyCellFormulaValues(mrDoc, *mrItem.mpCellFormulaValues);
+    }
+};
+
+}
+
+FormulaBuffer::SharedFormulaEntry::SharedFormulaEntry(
+    const table::CellAddress& rAddr, const table::CellRangeAddress& rRange,
+    const OUString& rTokenStr, sal_Int32 nSharedId ) :
+    maAddress(rAddr), maRange(rRange), maTokenStr(rTokenStr), mnSharedId(nSharedId) {}
+
+FormulaBuffer::SharedFormulaDesc::SharedFormulaDesc(
+    const com::sun::star::table::CellAddress& rAddr, sal_Int32 nSharedId,
+    const OUString& rCellValue, sal_Int32 nValueType ) :
+    maAddress(rAddr), mnSharedId(nSharedId), maCellValue(rCellValue), mnValueType(nValueType) {}
+
+FormulaBuffer::SheetItem::SheetItem() :
+    mpCellFormulas(NULL),
+    mpArrayFormulas(NULL),
+    mpCellFormulaValues(NULL),
+    mpSharedFormulaEntries(NULL),
+    mpSharedFormulaIDs(NULL) {}
+
+FormulaBuffer::FinalizeThread::FinalizeThread( FormulaBuffer& rParent, size_t nThreadCount ) :
+    salhelper::Thread("xlsx-import-formula-buffer-finalize-thread"),
+    mrParent(rParent), mnThreadCount(nThreadCount) {}
+
+FormulaBuffer::FinalizeThread::~FinalizeThread() {}
+
+void FormulaBuffer::FinalizeThread::execute()
+{
+    ScDocumentImport& rDoc = mrParent.getDocImport();
+    rDoc.getDoc().SetAutoNameCache(new ScAutoNameCache(&rDoc.getDoc()));
+    SCTAB nTabCount = rDoc.getDoc().GetTableCount();
+
+    std::vector<SheetItem> aSheetItems;
+    aSheetItems.reserve(nTabCount);
+    for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
+        aSheetItems.push_back(mrParent.getSheetItem(nTab));
+
+    typedef rtl::Reference<WorkerThread> WorkerThreadRef;
+    std::vector<WorkerThreadRef> aThreads;
+    aThreads.reserve(mnThreadCount);
+
+    std::vector<SheetItem>::iterator it = aSheetItems.begin(), itEnd = aSheetItems.end();
+
+    while (it != itEnd)
+    {
+        for (size_t i = 0; i < mnThreadCount; ++i)
+        {
+            if (it == itEnd)
+                break;
+
+            WorkerThreadRef xThread(new WorkerThread(rDoc, *it, rDoc.getDoc().CreateFormatTable()));
+            ++it;
+            aThreads.push_back(xThread);
+            xThread->launch();
+        }
+
+        for (size_t i = 0, n = aThreads.size(); i < n; ++i)
+        {
+            if (aThreads[i].is())
+                aThreads[i]->join();
+        }
+
+        aThreads.clear();
+    }
+
+    rDoc.getDoc().SetAutoNameCache(NULL);
+}
+
+FormulaBuffer::FormulaBuffer( const WorkbookHelper& rHelper ) : WorkbookHelper( rHelper )
+{
+}
+
+void FormulaBuffer::finalizeImport()
+{
+    ISegmentProgressBarRef xFormulaBar = getProgressBar().createSegment( getProgressBar().getFreeLength() );
+
+    rtl::Reference<FinalizeThread> xThreadMgr(new FinalizeThread(*this, 1));
+    xThreadMgr->launch();
+
+    if (xThreadMgr.is())
+        xThreadMgr->join();
+
+    xFormulaBar->setPosition( 1.0 );
+}
+
+FormulaBuffer::SheetItem FormulaBuffer::getSheetItem( SCTAB nTab )
+{
+    osl::MutexGuard aGuard(&maMtxData);
+
+    SheetItem aItem;
+    {
+        FormulaDataMap::iterator it = maCellFormulas.find(nTab);
+        if (it != maCellFormulas.end())
+            aItem.mpCellFormulas = &it->second;
+    }
+
+    {
+        ArrayFormulaDataMap::iterator it = maCellArrayFormulas.find(nTab);
+        if (it != maCellArrayFormulas.end())
+            aItem.mpArrayFormulas = &it->second;
+    }
+
+    {
+        FormulaValueMap::iterator it = maCellFormulaValues.find(nTab);
+        if (it != maCellFormulaValues.end())
+            aItem.mpCellFormulaValues = &it->second;
+    }
+
+    {
+        SheetToFormulaEntryMap::iterator it = maSharedFormulas.find(nTab);
+        if (it != maSharedFormulas.end())
+            aItem.mpSharedFormulaEntries = &it->second;
+    }
+
+    {
+        SheetToSharedFormulaid::iterator it = maSharedFormulaIds.find(nTab);
+        if (it != maSharedFormulaIds.end())
+            aItem.mpSharedFormulaIDs = &it->second;
     }
+    return aItem;
 }
 
 void FormulaBuffer::createSharedFormulaMapEntry(
commit 1cefb146a878080ff8609c9af21c1e494af1245b
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Nov 6 18:43:47 2013 -0500

    Allow instantiation of more than one SvNumberFormatter from the document.
    
    Change-Id: Ide6875e031268337bf6a21286176a38905c12691

diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 6929e9b..09f1466 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -1621,6 +1621,7 @@ public:
         const ScMarkData* pMarkData = NULL );
 
     SC_DLLPUBLIC SvNumberFormatter* GetFormatTable() const;
+    SC_DLLPUBLIC SvNumberFormatter* CreateFormatTable() const;
 
     void            Sort( SCTAB nTab, const ScSortParam& rSortParam, bool bKeepQuery, ScProgress* pProgress );
     SCSIZE          Query( SCTAB nTab, const ScQueryParam& rQueryParam, bool bKeepSub );
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index 1e0bb87..23a4bcf 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -491,6 +491,11 @@ SvNumberFormatter* ScDocument::GetFormatTable() const
     return xPoolHelper->GetFormTable();
 }
 
+SvNumberFormatter* ScDocument::CreateFormatTable() const
+{
+    return xPoolHelper->CreateNumberFormatter();
+}
+
 SfxItemPool* ScDocument::GetEditPool() const
 {
     return xPoolHelper->GetEditPool();
diff --git a/sc/source/core/data/poolhelp.cxx b/sc/source/core/data/poolhelp.cxx
index b6f027a..74d5cbe 100644
--- a/sc/source/core/data/poolhelp.cxx
+++ b/sc/source/core/data/poolhelp.cxx
@@ -71,14 +71,8 @@ SfxItemPool*        ScPoolHelper::GetEnginePool() const
 }
 SvNumberFormatter*  ScPoolHelper::GetFormTable() const
 {
-    if ( !pFormTable )
-    {
-        pFormTable = new SvNumberFormatter( comphelper::getProcessComponentContext(), ScGlobal::eLnge );
-        pFormTable->SetColorLink( LINK( m_pSourceDoc, ScDocument, GetUserDefinedColor ) );
-        pFormTable->SetEvalDateFormat( NF_EVALDATEFORMAT_INTL_FORMAT );
-
-        UseDocOptions();        // null date, year2000, std precision
-    }
+    if (!pFormTable)
+        pFormTable = CreateNumberFormatter();
     return pFormTable;
 }
 
@@ -100,6 +94,24 @@ void ScPoolHelper::SetFormTableOpt(const ScDocOptions& rOpt)
     UseDocOptions();        // #i105512# if the number formatter exists, update its settings
 }
 
+SvNumberFormatter* ScPoolHelper::CreateNumberFormatter() const
+{
+    SvNumberFormatter* p = NULL;
+    {
+        osl::MutexGuard aGuard(&maMtxCreateNumFormatter);
+        p = new SvNumberFormatter(comphelper::getProcessComponentContext(), ScGlobal::eLnge);
+    }
+    p->SetColorLink( LINK(m_pSourceDoc, ScDocument, GetUserDefinedColor) );
+    p->SetEvalDateFormat(NF_EVALDATEFORMAT_INTL_FORMAT);
+
+    sal_uInt16 d,m,y;
+    aOpt.GetDate(d, m, y);
+    p->ChangeNullDate(d, m, y);
+    p->ChangeStandardPrec(aOpt.GetStdPrecision());
+    p->SetYear2000(aOpt.GetYear2000());
+    return p;
+}
+
 void ScPoolHelper::SourceDocumentGone()
 {
     //  reset all pointers to the source document
diff --git a/sc/source/core/inc/poolhelp.hxx b/sc/source/core/inc/poolhelp.hxx
index 6eaa0a9..c60bd1b 100644
--- a/sc/source/core/inc/poolhelp.hxx
+++ b/sc/source/core/inc/poolhelp.hxx
@@ -23,6 +23,7 @@
 #include <rtl/ref.hxx>
 #include <salhelper/simplereferenceobject.hxx>
 #include "docoptio.hxx"
+#include "osl/mutex.hxx"
 
 class ScDocument;
 class ScDocumentPool;
@@ -34,6 +35,7 @@ class SfxItemPool;
 class ScPoolHelper : public salhelper::SimpleReferenceObject
 {
 private:
+    mutable osl::Mutex maMtxCreateNumFormatter;
     ScDocOptions        aOpt;
     ScDocumentPool*     pDocPool;
     rtl::Reference< ScStyleSheetPool > mxStylePool;
@@ -59,6 +61,8 @@ public:
     SfxItemPool*        GetEnginePool() const;
 
     void                SetFormTableOpt(const ScDocOptions& rOpt);
+
+    SvNumberFormatter* CreateNumberFormatter() const;
 };
 
 #endif
commit db9a73d51823a0c8392cc426da8f96ff69209832
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Nov 6 18:41:18 2013 -0500

    Allow non-pooled instance of SvNumberFormatter inside ScCompiler.
    
    Change-Id: I645079254621c2f2684a69116b094e37e46f46f4

diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx
index c16f749..0cd47c5 100644
--- a/sc/inc/compiler.hxx
+++ b/sc/inc/compiler.hxx
@@ -312,6 +312,8 @@ private:
     ScDocument* pDoc;
     ScAddress   aPos;
 
+    SvNumberFormatter* mpFormatter;
+
     // For CONV_XL_OOX, may be set via API by MOOXML filter.
     ::com::sun::star::uno::Sequence< const ::com::sun::star::sheet::ExternalLinkInfo > maExternalLinks;
 
@@ -400,6 +402,7 @@ public:
 
     void            SetGrammar( const formula::FormulaGrammar::Grammar eGrammar );
 
+    void SetNumberFormatter( SvNumberFormatter* pFormatter );
     EncodeUrlMode   GetEncodeUrlMode() const;
 private:
     /** Set grammar and reference convention from within SetFormulaLanguage()
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 6b6d011..9b77a7d 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -239,6 +239,11 @@ void ScCompiler::SetGrammar( const FormulaGrammar::Grammar eGrammar )
     }
 }
 
+void ScCompiler::SetNumberFormatter( SvNumberFormatter* pFormatter )
+{
+    mpFormatter = pFormatter;
+}
+
 ScCompiler::EncodeUrlMode ScCompiler::GetEncodeUrlMode() const
 {
     return meEncodeUrlMode;
@@ -1640,6 +1645,7 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos,ScTokenArra
         : FormulaCompiler(rArr),
         pDoc( pDocument ),
         aPos( rPos ),
+        mpFormatter(pDoc->GetFormatTable()),
         pCharClass( ScGlobal::pCharClass ),
         mnPredetectedReference(0),
         mnRangeOpPosInSymbol(-1),
@@ -1656,6 +1662,7 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos)
         :
         pDoc( pDocument ),
         aPos( rPos ),
+        mpFormatter(pDoc->GetFormatTable()),
         pCharClass( ScGlobal::pCharClass ),
         mnPredetectedReference(0),
         mnRangeOpPosInSymbol(-1),
@@ -2517,40 +2524,37 @@ bool ScCompiler::IsOpCode2( const OUString& rName )
 bool ScCompiler::IsValue( const OUString& rSym )
 {
     double fVal;
-    sal_uInt32 nIndex = ( mxSymbols->isEnglish() ?
-        pDoc->GetFormatTable()->GetStandardIndex( LANGUAGE_ENGLISH_US ) : 0 );
+    sal_uInt32 nIndex = mxSymbols->isEnglish() ? mpFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US) : 0;
 
-    if (pDoc->GetFormatTable()->IsNumberFormat( rSym, nIndex, fVal ) )
-    {
-        sal_uInt16 nType = pDoc->GetFormatTable()->GetType(nIndex);
+    if (!mpFormatter->IsNumberFormat(rSym, nIndex, fVal))
+        return false;
 
-        // Don't accept 3:3 as time, it is a reference to entire row 3 instead.
-        // Dates should never be entered directly and automatically converted
-        // to serial, because the serial would be wrong if null-date changed.
-        // Usually it wouldn't be accepted anyway because the date separator
-        // clashed with other separators or operators.
-        if (nType & (NUMBERFORMAT_TIME | NUMBERFORMAT_DATE))
-            return false;
+    sal_uInt16 nType = mpFormatter->GetType(nIndex);
 
-        if (nType == NUMBERFORMAT_LOGICAL)
-        {
-            const sal_Unicode* p = aFormula.getStr() + nSrcPos;
-            while( *p == ' ' )
-                p++;
-            if (*p == '(')
-                return false;   // Boolean function instead.
-        }
+    // Don't accept 3:3 as time, it is a reference to entire row 3 instead.
+    // Dates should never be entered directly and automatically converted
+    // to serial, because the serial would be wrong if null-date changed.
+    // Usually it wouldn't be accepted anyway because the date separator
+    // clashed with other separators or operators.
+    if (nType & (NUMBERFORMAT_TIME | NUMBERFORMAT_DATE))
+        return false;
 
-        if( nType == NUMBERFORMAT_TEXT )
-            // HACK: number too big!
-            SetError( errIllegalArgument );
-        ScRawToken aToken;
-        aToken.SetDouble( fVal );
-        pRawToken = aToken.Clone();
-        return true;
+    if (nType == NUMBERFORMAT_LOGICAL)
+    {
+        const sal_Unicode* p = aFormula.getStr() + nSrcPos;
+        while( *p == ' ' )
+            p++;
+        if (*p == '(')
+            return false;   // Boolean function instead.
     }
-    else
-        return false;
+
+    if( nType == NUMBERFORMAT_TEXT )
+        // HACK: number too big!
+        SetError( errIllegalArgument );
+    ScRawToken aToken;
+    aToken.SetDouble( fVal );
+    pRawToken = aToken.Clone();
+    return true;
 }
 
 bool ScCompiler::IsString()
commit 4efc5fa37681e1e0ff3cfffab8a4ea33f24b5ba0
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Nov 6 18:34:18 2013 -0500

    Protect those global symbols containers with mutex during initialization.
    
    Change-Id: Id15b3e1a2bfebd2ea795fd412a259f125f5d9bab

diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index fda54bd..804fb03 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -24,6 +24,8 @@
 #include "core_resource.hxx"
 #include "core_resource.hrc"
 
+#include "osl/mutex.hxx"
+
 #include <svl/zforlist.hxx>
 #include <tools/rc.hxx>
 #include <tools/rcid.h>
@@ -39,8 +41,7 @@ namespace formula
 
     static const sal_Char* pInternal[ 1 ] = { "TTT" };
 
-namespace
-{
+namespace {
 
 class FormulaCompilerRecursionGuard
 {
@@ -248,6 +249,13 @@ const sal_Unicode* lcl_UnicodeStrChr( const sal_Unicode* pStr, sal_Unicode c )
     return NULL;
 }
 
+struct OpCodeMapData
+{
+    FormulaCompiler::NonConstOpCodeMapPtr mxSymbolMap;
+    osl::Mutex maMtx;
+};
+
+
 } // namespace
 
 
@@ -625,21 +633,25 @@ FormulaCompiler::OpCodeMapPtr FormulaCompiler::CreateOpCodeMap(
 
 void lcl_fillNativeSymbols( FormulaCompiler::NonConstOpCodeMapPtr& xMap, bool bDestroy = false )
 {
-    static FormulaCompiler::NonConstOpCodeMapPtr s_SymbolMap;
+    static OpCodeMapData aSymbolMap;
+    osl::MutexGuard aGuard(&aSymbolMap.maMtx);
+
     if ( bDestroy )
     {
-        s_SymbolMap.reset();
+        aSymbolMap.mxSymbolMap.reset();
     }
-    else if ( !s_SymbolMap.get() )
+    else if (!aSymbolMap.mxSymbolMap)
     {
         // Core
-        s_SymbolMap.reset( new FormulaCompiler::OpCodeMap( SC_OPCODE_LAST_OPCODE_ID + 1, true,
-                    FormulaGrammar::GRAM_NATIVE_UI));
+        aSymbolMap.mxSymbolMap.reset(
+            new FormulaCompiler::OpCodeMap(
+                SC_OPCODE_LAST_OPCODE_ID + 1, true, FormulaGrammar::GRAM_NATIVE_UI));
         OModuleClient aModuleClient;
-        OpCodeList aOpCodeListNative( RID_STRLIST_FUNCTION_NAMES, s_SymbolMap );
+        OpCodeList aOpCodeListNative(RID_STRLIST_FUNCTION_NAMES, aSymbolMap.mxSymbolMap);
         // No AddInMap for native core mapping.
     }
-    xMap = s_SymbolMap;
+
+    xMap = aSymbolMap.mxSymbolMap;
 }
 
 const OUString& FormulaCompiler::GetNativeSymbol( OpCode eOp )
@@ -661,34 +673,38 @@ void FormulaCompiler::InitSymbolsNative() const
 
 void FormulaCompiler::InitSymbolsEnglish() const
 {
-    static NonConstOpCodeMapPtr s_sSymbol;
-    if ( !s_sSymbol.get() )
-        loadSymbols( RID_STRLIST_FUNCTION_NAMES_ENGLISH, FormulaGrammar::GRAM_ENGLISH, s_sSymbol);
-    mxSymbolsEnglish = s_sSymbol;
+    static OpCodeMapData aMap;
+    osl::MutexGuard aGuard(&aMap.maMtx);
+    if (!aMap.mxSymbolMap)
+        loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH, FormulaGrammar::GRAM_ENGLISH, aMap.mxSymbolMap);
+    mxSymbolsEnglish = aMap.mxSymbolMap;
 }
 
 void FormulaCompiler::InitSymbolsPODF() const
 {
-    static NonConstOpCodeMapPtr s_sSymbol;
-    if ( !s_sSymbol.get() )
-        loadSymbols( RID_STRLIST_FUNCTION_NAMES_ENGLISH, FormulaGrammar::GRAM_PODF, s_sSymbol);
-    mxSymbolsPODF = s_sSymbol;
+    static OpCodeMapData aMap;
+    osl::MutexGuard aGuard(&aMap.maMtx);
+    if (!aMap.mxSymbolMap)
+        loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH, FormulaGrammar::GRAM_PODF, aMap.mxSymbolMap);
+    mxSymbolsPODF = aMap.mxSymbolMap;
 }
 
 void FormulaCompiler::InitSymbolsODFF() const
 {
-    static NonConstOpCodeMapPtr s_sSymbol;
-    if ( !s_sSymbol.get() )
-        loadSymbols( RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF, FormulaGrammar::GRAM_ODFF, s_sSymbol);
-    mxSymbolsODFF = s_sSymbol;
+    static OpCodeMapData aMap;
+    osl::MutexGuard aGuard(&aMap.maMtx);
+    if (!aMap.mxSymbolMap)
+        loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF, FormulaGrammar::GRAM_ODFF, aMap.mxSymbolMap);
+    mxSymbolsODFF = aMap.mxSymbolMap;
 }
 
 void FormulaCompiler::InitSymbolsEnglishXL() const
 {
-    static NonConstOpCodeMapPtr s_sSymbol;
-    if ( !s_sSymbol.get() )
-        loadSymbols( RID_STRLIST_FUNCTION_NAMES_ENGLISH, FormulaGrammar::GRAM_ENGLISH, s_sSymbol);
-    mxSymbolsEnglishXL = s_sSymbol;
+    static OpCodeMapData aMap;
+    osl::MutexGuard aGuard(&aMap.maMtx);
+    if (!aMap.mxSymbolMap)
+        loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH, FormulaGrammar::GRAM_ENGLISH, aMap.mxSymbolMap);
+    mxSymbolsEnglishXL = aMap.mxSymbolMap;
 
     // TODO: For now, just replace the separators to the Excel English
     // variants. Later, if we want to properly map Excel functions with Calc
commit 88357ee6f4f0b6c42b2b07eae3cbe59d62075896
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Nov 6 14:55:41 2013 -0500

    Make TransformInput() a non-member function.
    
    Change-Id: Ieb077b6ce661e2885d6010519f137235a048f9df

diff --git a/svl/source/numbers/zforfind.cxx b/svl/source/numbers/zforfind.cxx
index 9cd3362..3726c33 100644
--- a/svl/source/numbers/zforfind.cxx
+++ b/svl/source/numbers/zforfind.cxx
@@ -147,8 +147,8 @@ inline bool ImpSvNumberInputScan::MyIsdigit( sal_Unicode c )
     return c < 128 && isdigit( (unsigned char) c );
 }
 
-
-void ImpSvNumberInputScan::TransformInput( OUString& rStr )
+// native number transliteration if necessary
+void TransformInput( SvNumberFormatter* pFormatter, OUString& rStr )
 {
     sal_Int32 nPos, nLen;
     for ( nPos = 0, nLen = rStr.getLength(); nPos < nLen; ++nPos )
@@ -3271,7 +3271,7 @@ bool ImpSvNumberInputScan::IsNumberFormat( const OUString& rString,         // s
         // NoMoreUpperNeeded, all comparisons on UpperCase
         aString = pFormatter->GetCharClass()->uppercase( rString );
         // convert native number to ASCII if necessary
-        TransformInput( aString );
+        TransformInput(pFormatter, aString);
         res = IsNumberFormatMain( aString, pFormat );
     }
 
diff --git a/svl/source/numbers/zforfind.hxx b/svl/source/numbers/zforfind.hxx
index 4c070a1..6e24040 100644
--- a/svl/source/numbers/zforfind.hxx
+++ b/svl/source/numbers/zforfind.hxx
@@ -362,9 +362,6 @@ private:
 
     static inline bool MyIsdigit( sal_Unicode c );
 
-    // native number transliteration if necessary
-    void TransformInput( OUString& rString );
-
     /** Whether input matches locale dependent date acceptance pattern.
 
         @param nStartPatternAt
commit 35a5999247bbb120dc677515d199b7da3c39146f
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Nov 5 19:06:15 2013 -0500

    Guard cache access with mutex & a new method just to check for range name.
    
    Change-Id: Id24b5ba72362f9d878b4878c1e807bed3e596b20

diff --git a/sc/inc/externalrefmgr.hxx b/sc/inc/externalrefmgr.hxx
index 6156abb..b3d35f9 100644
--- a/sc/inc/externalrefmgr.hxx
+++ b/sc/inc/externalrefmgr.hxx
@@ -233,6 +233,7 @@ public:
 
     ScExternalRefCache::TokenArrayRef getRangeNameTokens(sal_uInt16 nFileId, const OUString& rName);
     void setRangeNameTokens(sal_uInt16 nFileId, const OUString& rName, TokenArrayRef pArray);
+    bool isValidRangeName(sal_uInt16 nFileId, const OUString& rName) const;
 
     void setCellData(sal_uInt16 nFileId, const OUString& rTabName,
                      SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uLong nFmtIndex);
@@ -557,6 +558,8 @@ public:
     ScExternalRefCache::TokenArrayRef getRangeNameTokens(
         sal_uInt16 nFileId, const OUString& rName, const ScAddress* pCurPos = NULL);
 
+    bool isValidRangeName(sal_uInt16 nFileId, const OUString& rName);
+
     OUString getOwnDocumentName() const;
     bool isOwnDocument(const OUString& rFile) const;
 
@@ -765,6 +768,12 @@ private:
 private:
     ScDocument* mpDoc;
 
+    /** Mutex for accessing cached data and/or source document shells. */
+    mutable osl::Mutex maMtxCacheAccess;
+
+    /** Mutex for source document meta-data access. */
+    mutable osl::Mutex maMtxSrcFiles;
+
     /** cache of referenced ranges and names from source documents. */
     ScExternalRefCache maRefCache;
 
@@ -798,7 +807,6 @@ private:
      * external document identifiers.
      */
     std::vector<SrcFileData> maSrcFiles;
-    mutable osl::Mutex maMtxSrcFiles;
 
     /** Status whether in reference marking state. See isInReferenceMarking(). */
     bool mbInReferenceMarking:1;
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 62bf259..6b6d011 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -2914,7 +2914,7 @@ bool ScCompiler::IsExternalNamedRange( const OUString& rSymbol )
     pRefMgr->convertToAbsName(aTmp);
     aFile = aTmp;
     sal_uInt16 nFileId = pRefMgr->getExternalFileId(aFile);
-    if (!pRefMgr->getRangeNameTokens(nFileId, aName).get())
+    if (!pRefMgr->isValidRangeName(nFileId, aName))
         // range name doesn't exist in the source document.
         return false;
 
diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index 1561cbb..9c07fd7 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -710,6 +710,18 @@ void ScExternalRefCache::setRangeNameTokens(sal_uInt16 nFileId, const OUString&
     pDoc->maRealRangeNameMap.insert(NamePairMap::value_type(aUpperName, rName));
 }
 
+bool ScExternalRefCache::isValidRangeName(sal_uInt16 nFileId, const OUString& rName) const
+{
+    osl::MutexGuard aGuard(&maMtxDocs);
+
+    DocItem* pDoc = getDocItem(nFileId);
+    if (!pDoc)
+        return false;
+
+    const RangeNameMap& rMap = pDoc->maRangeNames;
+    return rMap.count(rName) > 0;
+}
+
 void ScExternalRefCache::setCellData(sal_uInt16 nFileId, const OUString& rTabName, SCCOL nCol, SCROW nRow,
                                      TokenRef pToken, sal_uLong nFmtIndex)
 {
@@ -1747,6 +1759,8 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
     sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rCell,
     const ScAddress* pCurPos, SCTAB* pTab, ScExternalRefCache::CellFormat* pFmt)
 {
+    osl::MutexGuard aGuard(&maMtxCacheAccess);
+
     if (pCurPos)
         insertRefCell(nFileId, *pCurPos);
 
@@ -1839,6 +1853,8 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
 ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(
     sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange, const ScAddress* pCurPos)
 {
+    osl::MutexGuard aGuard(&maMtxCacheAccess);
+
     if (pCurPos)
         insertRefCell(nFileId, *pCurPos);
 
@@ -1885,6 +1901,8 @@ ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(
 ScExternalRefCache::TokenArrayRef ScExternalRefManager::getRangeNameTokens(
     sal_uInt16 nFileId, const OUString& rName, const ScAddress* pCurPos)
 {
+    osl::MutexGuard aGuard(&maMtxCacheAccess);
+
     if (pCurPos)
         insertRefCell(nFileId, *pCurPos);
 
@@ -1924,6 +1942,42 @@ ScExternalRefCache::TokenArrayRef ScExternalRefManager::getRangeNameTokens(
     return pArray;
 }
 
+namespace {
+
+bool hasRangeName(ScDocument& rDoc, const OUString& rName)
+{
+    ScRangeName* pExtNames = rDoc.GetRangeName();
+    OUString aUpperName = ScGlobal::pCharClass->uppercase(rName);
+    const ScRangeData* pRangeData = pExtNames->findByUpperName(aUpperName);
+    return pRangeData != NULL;
+}
+
+}
+
+bool ScExternalRefManager::isValidRangeName(sal_uInt16 nFileId, const OUString& rName)
+{
+    osl::MutexGuard aGuard(&maMtxCacheAccess);
+
+    maybeLinkExternalFile(nFileId);
+    ScDocument* pSrcDoc = getInMemorySrcDocument(nFileId);
+    if (pSrcDoc)
+    {
+        // Only check the presence of the name.
+        return hasRangeName(*pSrcDoc, rName);
+    }
+
+    if (maRefCache.isValidRangeName(nFileId, rName))
+        // Range name is cached.
+        return true;
+
+    pSrcDoc = getSrcDocument(nFileId);
+    if (!pSrcDoc)
+        // failed to load document from disk.
+        return false;
+
+    return hasRangeName(*pSrcDoc, rName);
+}
+
 void ScExternalRefManager::refreshAllRefCells(sal_uInt16 nFileId)
 {
     RefCellMap::iterator itrFile = maRefCells.find(nFileId);
commit 719c3fb46bb38c69daea617ea9aaafc72505684d
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Nov 5 17:10:24 2013 -0500

    Add mutex for external source document meta-data container.
    
    These get updated from reference parser code (ScAddress, ScRange etc)
    which may be run from multiple threads.
    
    Change-Id: I5a1aaa4b51d9b9fb032458eb5e89f0652887184e

diff --git a/sc/inc/externalrefmgr.hxx b/sc/inc/externalrefmgr.hxx
index c5a73ae..6156abb 100644
--- a/sc/inc/externalrefmgr.hxx
+++ b/sc/inc/externalrefmgr.hxx
@@ -793,8 +793,12 @@ private:
 
     NumFmtMap maNumFormatMap;
 
-    /** original source file index. */
-    ::std::vector<SrcFileData> maSrcFiles;
+    /**
+     * List of external source document meta-data, used to keep track of
+     * external document identifiers.
+     */
+    std::vector<SrcFileData> maSrcFiles;
+    mutable osl::Mutex maMtxSrcFiles;
 
     /** Status whether in reference marking state. See isInReferenceMarking(). */
     bool mbInReferenceMarking:1;
diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index f7d026b..1561cbb 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -1594,6 +1594,7 @@ void ScExternalRefManager::getAllCachedNumberFormats(vector<sal_uInt32>& rNumFmt
 
 sal_uInt16 ScExternalRefManager::getExternalFileCount() const
 {
+    osl::MutexGuard aGuard(&maMtxSrcFiles);
     return static_cast< sal_uInt16 >( maSrcFiles.size() );
 }
 
@@ -2360,6 +2361,7 @@ void ScExternalRefManager::SrcFileData::maybeCreateRealFileName(const OUString&
 
 void ScExternalRefManager::maybeCreateRealFileName(sal_uInt16 nFileId)
 {
+    osl::MutexGuard aGuard(&maMtxSrcFiles);
     if (nFileId >= maSrcFiles.size())
         return;
 
@@ -2404,6 +2406,8 @@ void ScExternalRefManager::convertToAbsName(OUString& rFile) const
 
 sal_uInt16 ScExternalRefManager::getExternalFileId(const OUString& rFile)
 {
+    osl::MutexGuard aGuard(&maMtxSrcFiles);
+
     vector<SrcFileData>::const_iterator itrBeg = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
     vector<SrcFileData>::const_iterator itr = find_if(itrBeg, itrEnd, FindSrcFileByName(rFile));
     if (itr != itrEnd)
@@ -2420,6 +2424,8 @@ sal_uInt16 ScExternalRefManager::getExternalFileId(const OUString& rFile)
 
 const OUString* ScExternalRefManager::getExternalFileName(sal_uInt16 nFileId, bool bForceOriginal)
 {
+    osl::MutexGuard aGuard(&maMtxSrcFiles);
+
     if (nFileId >= maSrcFiles.size())
         return NULL;
 
@@ -2436,11 +2442,14 @@ const OUString* ScExternalRefManager::getExternalFileName(sal_uInt16 nFileId, bo
 
 bool ScExternalRefManager::hasExternalFile(sal_uInt16 nFileId) const
 {
+    osl::MutexGuard aGuard(&maMtxSrcFiles);
     return nFileId < maSrcFiles.size();
 }
 
 bool ScExternalRefManager::hasExternalFile(const OUString& rFile) const
 {
+    osl::MutexGuard aGuard(&maMtxSrcFiles);
+
     vector<SrcFileData>::const_iterator itrBeg = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
     vector<SrcFileData>::const_iterator itr = find_if(itrBeg, itrEnd, FindSrcFileByName(rFile));
     return itr != itrEnd;
@@ -2539,6 +2548,8 @@ void ScExternalRefManager::breakLink(sal_uInt16 nFileId)
 
 void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const OUString& rNewFile, const OUString& rNewFilter)
 {
+    osl::MutexGuard aGuard(&maMtxSrcFiles);
+
     maSrcFiles[nFileId].maFileName = rNewFile;
     maSrcFiles[nFileId].maRelativeName = OUString();
     maSrcFiles[nFileId].maRealFileName = OUString();
@@ -2553,6 +2564,8 @@ void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const OUString& rNe
 
 void ScExternalRefManager::setRelativeFileName(sal_uInt16 nFileId, const OUString& rRelUrl)
 {
+    osl::MutexGuard aGuard(&maMtxSrcFiles);
+
     if (nFileId >= maSrcFiles.size())
         return;
     maSrcFiles[nFileId].maRelativeName = rRelUrl;
@@ -2560,6 +2573,8 @@ void ScExternalRefManager::setRelativeFileName(sal_uInt16 nFileId, const OUStrin
 
 void ScExternalRefManager::setFilterData(sal_uInt16 nFileId, const OUString& rFilterName, const OUString& rOptions)
 {
+    osl::MutexGuard aGuard(&maMtxSrcFiles);
+
     if (nFileId >= maSrcFiles.size())
         return;
     maSrcFiles[nFileId].maFilterName = rFilterName;
@@ -2578,11 +2593,13 @@ void ScExternalRefManager::clear()
 
 bool ScExternalRefManager::hasExternalData() const
 {
+    osl::MutexGuard aGuard(&maMtxSrcFiles);
     return !maSrcFiles.empty();
 }
 
 void ScExternalRefManager::resetSrcFileData(const OUString& rBaseFileUrl)
 {
+    osl::MutexGuard aGuard(&maMtxSrcFiles);
     for (vector<SrcFileData>::iterator itr = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
           itr != itrEnd; ++itr)
     {
@@ -2598,6 +2615,7 @@ void ScExternalRefManager::resetSrcFileData(const OUString& rBaseFileUrl)
 
 void ScExternalRefManager::updateAbsAfterLoad()
 {
+    osl::MutexGuard aGuard(&maMtxSrcFiles);
     OUString aOwn( getOwnDocumentName() );
     for (vector<SrcFileData>::iterator itr = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
           itr != itrEnd; ++itr)
commit 112fb381299ed917b729b17066974a3dc9c3bafd
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Nov 5 16:55:54 2013 -0500

    Make this method private as it is used only internally.
    
    Change-Id: I752c9a6bcd7f5b057cd517a9630a975009d6fb0d

diff --git a/sc/inc/externalrefmgr.hxx b/sc/inc/externalrefmgr.hxx
index 21e4e75a..c5a73ae 100644
--- a/sc/inc/externalrefmgr.hxx
+++ b/sc/inc/externalrefmgr.hxx
@@ -669,14 +669,6 @@ public:
      */
     bool isFileLoadable(const OUString& rFile) const;
 
-    /**
-     * If in maUnsavedDocShells move it to maDocShells and create a correct
-     * external reference entry
-     *
-     * @param Pointer to the newly saved DocumentShell
-     */
-    void transformUnsavedRefToSavedRef( SfxObjectShell* pShell );
-
     virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
 
     /**
@@ -762,6 +754,13 @@ private:
 
     sal_uInt32 getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, const ScDocument* pSrcDoc);
 
+    /**
+     * If in maUnsavedDocShells move it to maDocShells and create a correct
+     * external reference entry
+     *
+     * @param Pointer to the newly saved DocumentShell
+     */
+    void transformUnsavedRefToSavedRef( SfxObjectShell* pShell );
 
 private:
     ScDocument* mpDoc;
commit 7d2619c9ad084237238b54a0e1c7a449fd7441be
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Nov 5 16:49:55 2013 -0500

    Set mutex for external ref cache content.
    
    Change-Id: Id00c0e553e08740df8d9b7eef19407e1b0d3f022

diff --git a/sc/inc/externalrefmgr.hxx b/sc/inc/externalrefmgr.hxx
index 9ade21d..21e4e75a 100644
--- a/sc/inc/externalrefmgr.hxx
+++ b/sc/inc/externalrefmgr.hxx
@@ -32,6 +32,7 @@
 #include "types.hxx"
 #include "rangelst.hxx"
 #include "formula/token.hxx"
+#include "osl/mutex.hxx"
 
 #include <boost/unordered_map.hpp>
 #include <boost/unordered_set.hpp>
@@ -340,6 +341,7 @@ private:
     DocItem* getDocItem(sal_uInt16 nFileId) const;
 
 private:
+    mutable osl::Mutex maMtxDocs;
     mutable DocDataType maDocs;
 };
 
@@ -682,7 +684,7 @@ public:
      *
      * @return true if the document still contains references to an unsaved file
      */
-    bool containsUnsavedReferences() { return !maUnsavedDocShells.empty(); }
+    bool containsUnsavedReferences() const { return !maUnsavedDocShells.empty(); }
 
     void insertRefCell(sal_uInt16 nFileId, const ScAddress& rCell);
 
diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index 676352a..f7d026b 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -494,6 +494,8 @@ ScExternalRefCache::~ScExternalRefCache() {}
 
 const OUString* ScExternalRefCache::getRealTableName(sal_uInt16 nFileId, const OUString& rTabName) const
 {
+    osl::MutexGuard aGuard(&maMtxDocs);
+
     DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
     if (itrDoc == maDocs.end())
     {
@@ -515,6 +517,8 @@ const OUString* ScExternalRefCache::getRealTableName(sal_uInt16 nFileId, const O
 
 const OUString* ScExternalRefCache::getRealRangeName(sal_uInt16 nFileId, const OUString& rRangeName) const
 {
+    osl::MutexGuard aGuard(&maMtxDocs);
+
     DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
     if (itrDoc == maDocs.end())
     {
@@ -535,6 +539,8 @@ const OUString* ScExternalRefCache::getRealRangeName(sal_uInt16 nFileId, const O
 ScExternalRefCache::TokenRef ScExternalRefCache::getCellData(
     sal_uInt16 nFileId, const OUString& rTabName, SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex)
 {
+    osl::MutexGuard aGuard(&maMtxDocs);
+
     DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
     if (itrDoc == maDocs.end())
     {
@@ -564,6 +570,8 @@ ScExternalRefCache::TokenRef ScExternalRefCache::getCellData(
 ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData(
     sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange)
 {
+    osl::MutexGuard aGuard(&maMtxDocs);
+
     DocDataType::iterator itrDoc = maDocs.find(nFileId);
     if (itrDoc == maDocs.end())
         // specified document is not cached.
@@ -673,6 +681,8 @@ ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData(
 
 ScExternalRefCache::TokenArrayRef ScExternalRefCache::getRangeNameTokens(sal_uInt16 nFileId, const OUString& rName)
 {
+    osl::MutexGuard aGuard(&maMtxDocs);
+
     DocItem* pDoc = getDocItem(nFileId);
     if (!pDoc)
         return TokenArrayRef();
@@ -688,6 +698,8 @@ ScExternalRefCache::TokenArrayRef ScExternalRefCache::getRangeNameTokens(sal_uIn
 
 void ScExternalRefCache::setRangeNameTokens(sal_uInt16 nFileId, const OUString& rName, TokenArrayRef pArray)
 {
+    osl::MutexGuard aGuard(&maMtxDocs);
+
     DocItem* pDoc = getDocItem(nFileId);
     if (!pDoc)
         return;
@@ -912,6 +924,8 @@ SCsTAB ScExternalRefCache::getTabSpan( sal_uInt16 nFileId, const OUString& rStar
 
 void ScExternalRefCache::getAllNumberFormats(vector<sal_uInt32>& rNumFmts) const
 {
+    osl::MutexGuard aGuard(&maMtxDocs);
+
     using ::std::sort;
     using ::std::unique;
 
@@ -986,6 +1000,8 @@ bool ScExternalRefCache::setCacheTableReferenced( sal_uInt16 nFileId, const OUSt
 
 void ScExternalRefCache::setAllCacheTableReferencedStati( bool bReferenced )
 {
+    osl::MutexGuard aGuard(&maMtxDocs);
+
     if (bReferenced)
     {
         maReferenced.reset(0);
@@ -1174,11 +1190,14 @@ ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nF
 
 void ScExternalRefCache::clearCache(sal_uInt16 nFileId)
 {
+    osl::MutexGuard aGuard(&maMtxDocs);
     maDocs.erase(nFileId);
 }
 
 ScExternalRefCache::DocItem* ScExternalRefCache::getDocItem(sal_uInt16 nFileId) const
 {
+    osl::MutexGuard aGuard(&maMtxDocs);
+
     using ::std::pair;
     DocDataType::iterator itrDoc = maDocs.find(nFileId);
     if (itrDoc == maDocs.end())
commit 29d1303e234d5d7ee2f312d28592869f020eb2f2
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Nov 5 16:25:16 2013 -0500

    Use atomic increment and decrement for thread-safe reference count.
    
    Change-Id: I630298b1c37a6d23c1aa17aabc1c9b2dcb48608a

diff --git a/include/formula/token.hxx b/include/formula/token.hxx
index 8fa8708..ea91e2c 100644
--- a/include/formula/token.hxx
+++ b/include/formula/token.hxx
@@ -29,6 +29,7 @@
 #include "formula/formuladllapi.h"
 #include "formula/types.hxx"
 #include "svl/sharedstring.hxx"
+#include "osl/interlck.h"
 
 namespace formula
 {
@@ -107,12 +108,18 @@ public:
             bool                IsFunction() const; // pure functions, no operators
             bool                IsExternalRef() const;
             sal_uInt8           GetParamCount() const;
-    inline  void                IncRef() const          { nRefCnt++; }
-    inline  void                DecRef() const
-                                    {
-                                        if (!--nRefCnt)
-                                            const_cast<FormulaToken*>(this)->Delete();
-                                    }
+
+    inline void IncRef() const
+    {
+        osl_atomic_increment(&nRefCnt);
+    }
+
+    inline void DecRef() const
+    {
+        if (!osl_atomic_decrement(&nRefCnt))
+            const_cast<FormulaToken*>(this)->Delete();
+    }
+
     inline  sal_uInt16          GetRef() const          { return nRefCnt; }
     inline OpCode               GetOpCode() const       { return eOp; }
 
commit 1d996cee76a50a5a6aa74e21eec89e03a05772e7
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Nov 5 14:55:21 2013 -0500

    Keep the integer type in sync and remove unused data members.
    
    Change-Id: Iaaf1ebddd3b946b3211952729d41b01f0967f374

diff --git a/sc/source/filter/inc/formulabuffer.hxx b/sc/source/filter/inc/formulabuffer.hxx
index dbb77bb..f9e5229 100644
--- a/sc/source/filter/inc/formulabuffer.hxx
+++ b/sc/source/filter/inc/formulabuffer.hxx
@@ -74,30 +74,26 @@ class FormulaBuffer : public WorkbookHelper
         TokenRangeAddressItem( const TokenAddressItem& rTokenAndAddress, const ::com::sun::star::table::CellRangeAddress& rCellRangeAddress ) : maTokenAndAddress( rTokenAndAddress ), maCellRangeAddress( rCellRangeAddress ) {}
     };
 
-    typedef ::std::map< sal_Int32, std::vector< TokenAddressItem > > FormulaDataMap;
-    typedef ::std::map< sal_Int32, std::vector< TokenRangeAddressItem > > ArrayFormulaDataMap;
+    typedef ::std::map< SCTAB, std::vector<TokenAddressItem> > FormulaDataMap;
+    typedef ::std::map< SCTAB, std::vector<TokenRangeAddressItem> > ArrayFormulaDataMap;
     // sheet -> list of shared formula descriptions
-    typedef ::std::map< sal_Int32, std::vector< SharedFormulaDesc > > SheetToSharedFormulaid;
+    typedef ::std::map< SCTAB, std::vector<SharedFormulaDesc> > SheetToSharedFormulaid;
     // sheet -> stuff needed to create shared formulae
-    typedef ::std::map< sal_Int32, std::vector< SharedFormulaEntry > >  SheetToFormulaEntryMap;
-    // sharedId -> tokedId
-    typedef ::std::map< sal_Int32, sal_Int32 > SharedIdToTokenIndex;
-    typedef ::std::map< sal_Int32, SharedIdToTokenIndex > SheetToSharedIdToTokenIndex;
+    typedef ::std::map< SCTAB, std::vector<SharedFormulaEntry> >  SheetToFormulaEntryMap;
+
     typedef ::std::pair< ::com::sun::star::table::CellAddress, double > ValueAddressPair;
-    typedef ::std::map< sal_Int32, std::vector< ValueAddressPair > > FormulaValueMap;
+    typedef ::std::map< SCTAB, std::vector<ValueAddressPair> > FormulaValueMap;
 
-    com::sun::star::uno::Reference< com::sun::star::sheet::XSpreadsheet > mxCurrSheet;
     FormulaDataMap maCellFormulas;
     ArrayFormulaDataMap maCellArrayFormulas;
     SheetToFormulaEntryMap maSharedFormulas;
     SheetToSharedFormulaid maSharedFormulaIds;
-    SheetToSharedIdToTokenIndex maTokenIndexes;
     FormulaValueMap maCellFormulaValues;
 
     void                applyArrayFormulas(  const std::vector< TokenRangeAddressItem >& rVector );
     void                applyCellFormulas(  const std::vector< TokenAddressItem >& rVector );
     void                applyCellFormulaValues( const std::vector< ValueAddressPair >& rVector );
-    void applySharedFormulas( sal_Int32 nTab );
+    void applySharedFormulas( SCTAB nTab );
 
 public:
     explicit            FormulaBuffer( const WorkbookHelper& rHelper );
diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx
index 68e1d2e..04be139 100644
--- a/sc/source/filter/oox/formulabuffer.cxx
+++ b/sc/source/filter/oox/formulabuffer.cxx
@@ -54,13 +54,11 @@ void FormulaBuffer::finalizeImport()
     ISegmentProgressBarRef xFormulaBar = getProgressBar().createSegment( getProgressBar().getFreeLength() );
 
     ScDocument& rDoc = getScDocument();
-    Reference< XIndexAccess > xSheets( getDocument()->getSheets(), UNO_QUERY_THROW );
     rDoc.SetAutoNameCache( new ScAutoNameCache( &rDoc ) );
-    for ( sal_Int32 nTab = 0, nElem = xSheets->getCount(); nTab < nElem; ++nTab )
+    for (SCTAB nTab = 0, nElem = rDoc.GetTableCount(); nTab < nElem; ++nTab)
     {
         double fPosition = static_cast< double> (nTab + 1) /static_cast<double>(nElem);
         xFormulaBar->setPosition( fPosition );
-        mxCurrSheet = getSheetFromDoc( nTab );
 
         applySharedFormulas(nTab);
 
@@ -122,7 +120,7 @@ void FormulaBuffer::applyCellFormulaValues( const std::vector< ValueAddressPair
     }
 }
 
-void FormulaBuffer::applySharedFormulas( sal_Int32 nTab )
+void FormulaBuffer::applySharedFormulas( SCTAB nTab )
 {
     SheetToFormulaEntryMap::const_iterator itShared = maSharedFormulas.find(nTab);
     if (itShared == maSharedFormulas.end())
commit 7045802f27f3efe74b4ed9146d33abe253df043a
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Nov 5 14:38:28 2013 -0500

    Add mutex to guard the shared string pool content.
    
    Change-Id: I0eb97d0fbeaefd8a1c86d240ed8bd7f208fb662e

diff --git a/include/svl/sharedstringpool.hxx b/include/svl/sharedstringpool.hxx
index 1b2796d..b2cb367 100644
--- a/include/svl/sharedstringpool.hxx
+++ b/include/svl/sharedstringpool.hxx
@@ -11,6 +11,7 @@
 #define INCLUDED_SVL_SHAREDSTRINGPOOL_HXX
 
 #include "svl/sharedstring.hxx"
+#include "osl/mutex.hxx"
 
 #include <boost/unordered_map.hpp>
 #include <boost/unordered_set.hpp>
@@ -30,6 +31,7 @@ class SVL_DLLPUBLIC SharedStringPool
     typedef std::pair<StrHashType::iterator, bool> InsertResultType;
     typedef boost::unordered_map<const rtl_uString*, OUString> StrStoreType;
 
+    mutable osl::Mutex maMutex;
     StrHashType maStrPool;
     StrHashType maStrPoolUpper;
     StrStoreType maStrStore;
diff --git a/svl/source/misc/sharedstringpool.cxx b/svl/source/misc/sharedstringpool.cxx
index 46bf814..1e85da5 100644
--- a/svl/source/misc/sharedstringpool.cxx
+++ b/svl/source/misc/sharedstringpool.cxx
@@ -17,6 +17,8 @@ SharedStringPool::SharedStringPool( const CharClass* pCharClass ) : mpCharClass(
 
 SharedString SharedStringPool::intern( const OUString& rStr )
 {
+    osl::MutexGuard aGuard(&maMutex);
+
     InsertResultType aRes = findOrInsert(maStrPool, rStr);
     if (aRes.first == maStrPool.end())
         // Insertion failed.
@@ -63,6 +65,8 @@ inline sal_Int32 getRefCount( const rtl_uString* p )
 
 void SharedStringPool::purge()
 {
+    osl::MutexGuard aGuard(&maMutex);
+
     StrHashType aNewStrPool;
     StrHashType::iterator it = maStrPool.begin(), itEnd = maStrPool.end();
     for (; it != itEnd; ++it)
@@ -98,11 +102,13 @@ void SharedStringPool::purge()
 
 size_t SharedStringPool::getCount() const
 {
+    osl::MutexGuard aGuard(&maMutex);
     return maStrPool.size();
 }
 
 size_t SharedStringPool::getCountIgnoreCase() const
 {
+    osl::MutexGuard aGuard(&maMutex);
     return maStrPoolUpper.size();
 }
 
commit 9611851a5349f564ba97bacd9619eb8b329ae283
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Nov 5 11:55:57 2013 -0500

    Avoid using an extra buffer when the name doesn't contain double-quotes.
    
    Change-Id: Idc76ccad114e5964f80c5a3c8c8da2a64c1a2b86

diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx
index 41aae82..ec9e088 100644
--- a/sc/source/core/tool/address.cxx
+++ b/sc/source/core/tool/address.cxx
@@ -47,6 +47,44 @@ ScAddress::Details::Details ( const ScDocument* pDoc,
 {
 }
 
+namespace {
+
+const sal_Unicode* parseQuotedNameWithBuffer( const sal_Unicode* pStart, const sal_Unicode* p, OUString& rName )
+{
+    // The current character must be on the 2nd quote.
+
+    // Push all the characters up to the current, but skip the very first
+    // character which is the opening quote.
+    OUStringBuffer aBuf(OUString(pStart+1, p-pStart-1));
+
+    ++p; // Skip the 2nd quote.
+    sal_Unicode cPrev = 0;
+    for (; *p; ++p)
+    {
+        if (*p == '\'')
+        {
+            if (cPrev == '\'')
+            {
+                // double single-quote equals one single quote.
+                aBuf.append(*p);
+                cPrev = 0;
+                continue;
+            }
+        }
+        else if (cPrev == '\'')
+        {
+            // We are past the closing quote.  We're done!
+            rName = aBuf.makeStringAndClear();
+            return p;
+        }
+        else
+            aBuf.append(*p);
+        cPrev = *p;
+    }
+
+    return pStart;
+}
+
 /**
  * Parse from the opening single quote to the closing single quote.  Inside
  * the quotes, a single quote character is encoded by double single-quote
@@ -59,13 +97,11 @@ ScAddress::Details::Details ( const ScDocument* pDoc,
  * @return pointer to the character immediately after the closing single
  *         quote.
  */
-static const sal_Unicode* lcl_ParseQuotedName( const sal_Unicode* p, OUString& rName )
+const sal_Unicode* parseQuotedName( const sal_Unicode* p, OUString& rName )
 {
-    rName = "";
     if (*p != '\'')
         return p;
 
-    OUStringBuffer aBuf;
     const sal_Unicode* pStart = p;
     sal_Unicode cPrev = 0;
     for (++p; *p; ++p)
@@ -75,25 +111,26 @@ static const sal_Unicode* lcl_ParseQuotedName( const sal_Unicode* p, OUString& r
             if (cPrev == '\'')
             {
                 // double single-quote equals one single quote.
-                aBuf.append(*p);
-                cPrev = 0;
-                continue;
+                return parseQuotedNameWithBuffer(pStart, p, rName);
             }
         }
         else if (cPrev == '\'')
         {
-            // We are past the closing quote.  We're done!
-            rName = aBuf.makeStringAndClear();
+            // We are past the closing quote.  We're done!  Skip the opening
+            // and closing quotes.
+            rName = OUString(pStart+1, p - pStart-2);
             return p;
         }
-        else
-            aBuf.append(*p);
+
         cPrev = *p;
     }
 
+    rName = "";
     return pStart;
 }
 
+}
+
 static long int
 sal_Unicode_strtol ( const sal_Unicode*  p,
                      const sal_Unicode** pEnd )
@@ -265,7 +302,7 @@ lcl_XL_ParseSheetRef( const sal_Unicode* start,
     }
     else if( *p == '\'')
     {
-        p = lcl_ParseQuotedName(p, aTabName);
+        p = parseQuotedName(p, aTabName);
         if (aTabName.isEmpty())
             return NULL;
     }
@@ -415,7 +452,7 @@ const sal_Unicode* ScRange::Parse_XL_Header(
         // single quote text inside the quoted text.
         if (*p == '\'')
         {
-            p = lcl_ParseQuotedName(p, rExternDocName);
+            p = parseQuotedName(p, rExternDocName);
             if (!*p || *p != ']' || rExternDocName.isEmpty())
             {
                 rExternDocName = "";
@@ -447,7 +484,7 @@ const sal_Unicode* ScRange::Parse_XL_Header(
         // Excel does not allow [ and ] characters in sheet names though.
         // But, more sickness comes with MOOXML as there may be
         // '[1]Sheet 4'!$A$1  where [1] is the external doc's index.
-        p = lcl_ParseQuotedName(p, rExternDocName);
+        p = parseQuotedName(p, rExternDocName);
         if (!*p || *p != '!')
         {
             rExternDocName = "";
@@ -1003,7 +1040,7 @@ lcl_ScAddress_Parse_OOo( const sal_Unicode* p, ScDocument* pDoc, ScAddress& rAdd
     {
         const sal_Unicode* pStart = p;
         OUString aTmp;
-        p = lcl_ParseQuotedName(p, aTmp);
+        p = parseQuotedName(p, aTmp);
         aDocName = aTmp;
         if (*p++ == SC_COMPILER_FILE_TAB_SEP)
             bExtDoc = true;
@@ -1036,7 +1073,7 @@ lcl_ScAddress_Parse_OOo( const sal_Unicode* p, ScDocument* pDoc, ScAddress& rAdd
             // Tokens that start at ' can have anything in them until a final
             // ' but '' marks an escaped '.  We've earlier guaranteed that a
             // string containing '' will be surrounded by '.
-            p = lcl_ParseQuotedName(p, aTab);
+            p = parseQuotedName(p, aTab);
         }
         else
         {
diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx
index bc074a2..68e1d2e 100644
--- a/sc/source/filter/oox/formulabuffer.cxx
+++ b/sc/source/filter/oox/formulabuffer.cxx
@@ -90,11 +90,11 @@ void FormulaBuffer::finalizeImport()
 void FormulaBuffer::applyCellFormulas( const std::vector< TokenAddressItem >& rVector )
 {
     ScDocumentImport& rDoc = getDocImport();
+    ScExternalRefManager::ApiGuard aExtRefGuard(&rDoc.getDoc());
     for ( std::vector< TokenAddressItem >::const_iterator it = rVector.begin(), it_end = rVector.end(); it != it_end; ++it )
     {
         ScAddress aPos;
         ScUnoConversion::FillScAddress(aPos, it->maCellAddress);
-        ScExternalRefManager::ApiGuard aExtRefGuard(&rDoc.getDoc());
         ScCompiler aCompiler(&rDoc.getDoc(), aPos);
         aCompiler.SetGrammar(formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX);
         ScTokenArray* pCode = aCompiler.CompileString(it->maTokenStr);
commit dd9b59ef1869509817aa093747142e1ab0c3adba
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Nov 5 11:00:05 2013 -0500

    Add new test for parsing OOo A1 style single references.
    
    Change-Id: I7644338bd536d16777d330a64764eb26ecda5da5

diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx
index b9c1d42..19c94d7 100644
--- a/sc/qa/unit/ucalc.hxx
+++ b/sc/qa/unit/ucalc.hxx
@@ -84,6 +84,7 @@ public:
     void testRangeList();
     void testInput();
 
+    void testFormulaParseReference();
     void testFetchVectorRefArray();
     void testFormulaHashAndTag();
     void testFormulaRefData();
@@ -292,6 +293,7 @@ public:
     CPPUNIT_TEST(testSharedStringPool);
     CPPUNIT_TEST(testRangeList);
     CPPUNIT_TEST(testInput);
+    CPPUNIT_TEST(testFormulaParseReference);
     CPPUNIT_TEST(testFetchVectorRefArray);
     CPPUNIT_TEST(testFormulaHashAndTag);
     CPPUNIT_TEST(testFormulaRefData);
diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index 9f824e5..ce407e7 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -73,6 +73,62 @@ bool equals( const formula::VectorRefArray& rArray, size_t nPos, const OUString&
 
 }
 
+void Test::testFormulaParseReference()
+{
+    OUString aTab1("90's Music"), aTab2("90's and 70's"), aTab3("All Others"), aTab4("NoQuote");
+    m_pDoc->InsertTab(0, "Dummy"); // just to shift the sheet indices...
+    m_pDoc->InsertTab(1, aTab1); // name with a single quote.
+    m_pDoc->InsertTab(2, aTab2); // name with 2 single quotes.
+    m_pDoc->InsertTab(3, aTab3); // name without single quotes.
+    m_pDoc->InsertTab(4, aTab4); // name that doesn't require to be quoted.
+
+    OUString aTabName;
+    m_pDoc->GetName(1, aTabName);
+    CPPUNIT_ASSERT_EQUAL(aTab1, aTabName);
+    m_pDoc->GetName(2, aTabName);
+    CPPUNIT_ASSERT_EQUAL(aTab2, aTabName);
+    m_pDoc->GetName(3, aTabName);
+    CPPUNIT_ASSERT_EQUAL(aTab3, aTabName);
+    m_pDoc->GetName(4, aTabName);
+    CPPUNIT_ASSERT_EQUAL(aTab4, aTabName);
+
+    ScAddress aPos;
+    ScAddress::ExternalInfo aExtInfo;
+    sal_uInt16 nRes = aPos.Parse("'90''s Music'.D10", m_pDoc, formula::FormulaGrammar::CONV_OOO, &aExtInfo);
+    CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes & SCA_VALID) != 0);
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCTAB>(1), aPos.Tab());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(3), aPos.Col());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(9), aPos.Row());
+    CPPUNIT_ASSERT_MESSAGE("This is not an external address.", !aExtInfo.mbExternal);
+
+    nRes = aPos.Parse("'90''s and 70''s'.C100", m_pDoc, formula::FormulaGrammar::CONV_OOO, &aExtInfo);
+    CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes & SCA_VALID) != 0);
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCTAB>(2), aPos.Tab());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(2), aPos.Col());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(99), aPos.Row());
+    CPPUNIT_ASSERT_MESSAGE("This is not an external address.", !aExtInfo.mbExternal);
+
+    nRes = aPos.Parse("'All Others'.B3", m_pDoc, formula::FormulaGrammar::CONV_OOO, &aExtInfo);
+    CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes & SCA_VALID) != 0);
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCTAB>(3), aPos.Tab());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(1), aPos.Col());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), aPos.Row());
+    CPPUNIT_ASSERT_MESSAGE("This is not an external address.", !aExtInfo.mbExternal);
+
+    nRes = aPos.Parse("NoQuote.E13", m_pDoc, formula::FormulaGrammar::CONV_OOO, &aExtInfo);
+    CPPUNIT_ASSERT_MESSAGE("Failed to parse.", (nRes & SCA_VALID) != 0);
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCTAB>(4), aPos.Tab());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(4), aPos.Col());
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(12), aPos.Row());
+    CPPUNIT_ASSERT_MESSAGE("This is not an external address.", !aExtInfo.mbExternal);
+
+    m_pDoc->DeleteTab(4);
+    m_pDoc->DeleteTab(3);
+    m_pDoc->DeleteTab(2);
+    m_pDoc->DeleteTab(1);
+    m_pDoc->DeleteTab(0);
+}
+
 void Test::testFetchVectorRefArray()
 {
     m_pDoc->InsertTab(0, "Test");
commit eced6da7455c671807d60becf3b2b549f39e87da
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Nov 4 23:31:51 2013 -0500

    Using OUStringBuffer is faster than chained += operator.
    
    Change-Id: I9991028ddd8ab6e2e43fe9a19428c9fdfbd38db6

diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx
index 7426f95..41aae82 100644
--- a/sc/source/core/tool/address.cxx
+++ b/sc/source/core/tool/address.cxx
@@ -65,6 +65,7 @@ static const sal_Unicode* lcl_ParseQuotedName( const sal_Unicode* p, OUString& r
     if (*p != '\'')
         return p;
 
+    OUStringBuffer aBuf;
     const sal_Unicode* pStart = p;
     sal_Unicode cPrev = 0;
     for (++p; *p; ++p)
@@ -74,19 +75,22 @@ static const sal_Unicode* lcl_ParseQuotedName( const sal_Unicode* p, OUString& r
             if (cPrev == '\'')
             {
                 // double single-quote equals one single quote.
-                rName += OUString(*p);
+                aBuf.append(*p);
                 cPrev = 0;
                 continue;
             }
         }
         else if (cPrev == '\'')
+        {
             // We are past the closing quote.  We're done!
+            rName = aBuf.makeStringAndClear();
             return p;
+        }
         else
-            rName += OUString(*p);
+            aBuf.append(*p);
         cPrev = *p;
     }
-    rName = "";
+
     return pStart;
 }
 
commit 04532617c7d264411563db24dc359326cc18eda7
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Nov 4 22:52:26 2013 -0500

    Avoid duplication of ScTokenArray during formula cell construction.
    
    For slightly less overhead.
    
    Change-Id: Ie5861d585d6e22fbd19dfd57edfebae4f4504839

diff --git a/sc/inc/documentimport.hxx b/sc/inc/documentimport.hxx
index d034292..d2aa994 100644
--- a/sc/inc/documentimport.hxx
+++ b/sc/inc/documentimport.hxx
@@ -67,7 +67,7 @@ public:
     void setStringCell(const ScAddress& rPos, const OUString& rStr);
     void setEditCell(const ScAddress& rPos, EditTextObject* pEditText);
     void setFormulaCell(const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar);
-    void setFormulaCell(const ScAddress& rPos, const ScTokenArray& rArray);
+    void setFormulaCell(const ScAddress& rPos, ScTokenArray* pArray);
     void setFormulaCell(const ScAddress& rPos, ScFormulaCell* pCell);
 
     void setMatrixCells(
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 46a68c4..c2e578b 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -153,6 +153,15 @@ public:
 
     ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos );
 
+    /**
+     * Transfer the ownership of the passed token array instance to the
+     * formula cell being constructed.  The caller <i>must not</i> pass a NULL
+     * token array pointer.
+     */
+    ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos, ScTokenArray* pArray,
+                   const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT,
+                   sal_uInt8 cMatInd = MM_NONE );
+
     ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos, const ScTokenArray& rArray,
                    const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT,
                    sal_uInt8 cMatInd = MM_NONE );
diff --git a/sc/source/core/data/documentimport.cxx b/sc/source/core/data/documentimport.cxx
index 93b43b0..7138795 100644
--- a/sc/source/core/data/documentimport.cxx
+++ b/sc/source/core/data/documentimport.cxx
@@ -202,7 +202,7 @@ void ScDocumentImport::setFormulaCell(
         rCells.set(pBlockPos->miCellPos, rPos.Row(), new ScFormulaCell(&mpImpl->mrDoc, rPos, rFormula, eGrammar));
 }
 
-void ScDocumentImport::setFormulaCell(const ScAddress& rPos, const ScTokenArray& rArray)
+void ScDocumentImport::setFormulaCell(const ScAddress& rPos, ScTokenArray* pArray)
 {
     ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
     if (!pTab)
@@ -216,7 +216,7 @@ void ScDocumentImport::setFormulaCell(const ScAddress& rPos, const ScTokenArray&
 
     sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
     pBlockPos->miCellPos =
-        rCells.set(pBlockPos->miCellPos, rPos.Row(), new ScFormulaCell(&mpImpl->mrDoc, rPos, rArray));
+        rCells.set(pBlockPos->miCellPos, rPos.Row(), new ScFormulaCell(&mpImpl->mrDoc, rPos, pArray));
 }
 
 void ScDocumentImport::setFormulaCell(const ScAddress& rPos, ScFormulaCell* pCell)
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 15c3b98..b0ffb74 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -487,6 +487,54 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
 }
 
 ScFormulaCell::ScFormulaCell(
+    ScDocument* pDoc, const ScAddress& rPos, ScTokenArray* pArray,
+    const FormulaGrammar::Grammar eGrammar, sal_uInt8 cMatInd ) :
+    eTempGrammar( eGrammar),
+    pCode(pArray),
+    pDocument( pDoc ),
+    pPrevious(0),
+    pNext(0),
+    pPreviousTrack(0),
+    pNextTrack(0),
+    nSeenInIteration(0),
+    cMatrixFlag ( cMatInd ),
+    nFormatType ( NUMBERFORMAT_NUMBER ),
+    bDirty( true ),
+    bChanged( false ),
+    bRunning( false ),
+    bCompile( false ),
+    bSubTotal( false ),
+    bIsIterCell( false ),
+    bInChangeTrack( false ),
+    bTableOpDirty( false ),
+    bNeedListening( false ),
+    mbNeedsNumberFormat( false ),
+    aPos( rPos )
+{
+    assert(pArray); // Never pass a NULL pointer here.
+
+    // Generate RPN token array.
+    if (pCode->GetLen() && !pCode->GetCodeError() && !pCode->GetCodeLen())
+    {
+        ScCompiler aComp( pDocument, aPos, *pCode);
+        aComp.SetGrammar(eTempGrammar);
+        bSubTotal = aComp.CompileTokenArray();
+        nFormatType = aComp.GetNumFormatType();
+    }
+    else
+    {
+        pCode->Reset();
+        if (pCode->GetNextOpCodeRPN(ocSubTotal))
+            bSubTotal = true;
+    }
+
+    if (bSubTotal)
+        pDocument->AddSubTotalCell(this);
+
+    pCode->GenHash();
+}
+
+ScFormulaCell::ScFormulaCell(
     ScDocument* pDoc, const ScAddress& rPos, const ScTokenArray& rArray,
     const FormulaGrammar::Grammar eGrammar, sal_uInt8 cMatInd ) :
     eTempGrammar( eGrammar),
diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx
index 3dde87b..bc074a2 100644
--- a/sc/source/filter/oox/formulabuffer.cxx
+++ b/sc/source/filter/oox/formulabuffer.cxx
@@ -27,8 +27,6 @@
 #include "externalrefmgr.hxx"
 #include "oox/token/tokens.hxx"
 
-#include <boost/scoped_ptr.hpp>
-
 using namespace com::sun::star;
 using namespace ::com::sun::star::uno;
 using namespace ::com::sun::star::table;
@@ -99,11 +97,11 @@ void FormulaBuffer::applyCellFormulas( const std::vector< TokenAddressItem >& rV
         ScExternalRefManager::ApiGuard aExtRefGuard(&rDoc.getDoc());
         ScCompiler aCompiler(&rDoc.getDoc(), aPos);
         aCompiler.SetGrammar(formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX);
-        boost::scoped_ptr<ScTokenArray> pCode(aCompiler.CompileString(it->maTokenStr));
+        ScTokenArray* pCode = aCompiler.CompileString(it->maTokenStr);
         if (!pCode)
             continue;
 
-        rDoc.setFormulaCell(aPos, *pCode);
+        rDoc.setFormulaCell(aPos, pCode);
     }
 }
 
diff --git a/sc/source/filter/oox/worksheethelper.cxx b/sc/source/filter/oox/worksheethelper.cxx
index fb5eadd..148118b 100644
--- a/sc/source/filter/oox/worksheethelper.cxx
+++ b/sc/source/filter/oox/worksheethelper.cxx
@@ -1583,7 +1583,7 @@ void WorksheetHelper::putFormulaTokens( const CellAddress& rAddress, const ApiTo
     ScAddress aCellPos;
     ScUnoConversion::FillScAddress( aCellPos, rAddress );
     ScTokenConversion::ConvertToTokenArray(rDoc.getDoc(), aTokenArray, rTokens);
-    rDoc.setFormulaCell(aCellPos, aTokenArray);
+    rDoc.setFormulaCell(aCellPos, new ScTokenArray(aTokenArray));
 }
 
 void WorksheetHelper::initializeWorksheetImport()
commit a09f7fddb4e847b35e6d47a45403c649152dd671
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon Nov 4 22:24:39 2013 -0500

    Modify ScFormulaCell's ctor to take a const reference to ScTokenArray.
    
    Instead of a pointer to ScTokenArray, and then clone its instance.  If
    the token array gets cloned in ctor, take a const reference.
    
    Change-Id: I280fd7eb9eaea9905dbf954a1ace904ab0814dfe

diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 9d27558..46a68c4 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -151,10 +151,11 @@ public:
 
     ScFormulaCell* Clone() const;
 
-    /** Empty formula cell, or with a preconstructed token array. */
-    ScFormulaCell( ScDocument*, const ScAddress&, const ScTokenArray* = NULL,
-                    const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT,
-                    sal_uInt8 = MM_NONE );
+    ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos );
+
+    ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos, const ScTokenArray& rArray,
+                   const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT,
+                   sal_uInt8 cMatInd = MM_NONE );
 
     ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos, const ScFormulaCellGroupRef& xGroup,
                    const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT,
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 512ccc5..12fc80a 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -1643,7 +1643,7 @@ class CopyAsLinkHandler
 
         ScTokenArray aArr;
         aArr.AddSingleReference(aRef);
-        return new ScFormulaCell(&mrDestCol.GetDoc(), ScAddress(mrDestCol.GetCol(), nRow, mrDestCol.GetTab()), &aArr);
+        return new ScFormulaCell(&mrDestCol.GetDoc(), ScAddress(mrDestCol.GetCol(), nRow, mrDestCol.GetTab()), aArr);
     }
 
     void createRefBlock(const sc::CellStoreType::value_type& aNode, size_t nOffset, size_t nDataSize)
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 61f5326..a400935 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -700,7 +700,7 @@ class CopyCellsFromClipHandler
         aArr.AddSingleReference(aRef);
 
         mrDestCol.SetFormulaCell(
-            maDestBlockPos, nDestRow, new ScFormulaCell(&mrDestCol.GetDoc(), aDestPos, &aArr));
+            maDestBlockPos, nDestRow, new ScFormulaCell(&mrDestCol.GetDoc(), aDestPos, aArr));
     }
 
     void duplicateNotes(SCROW nStartRow, size_t nDataSize, bool bCloneCaption )
@@ -968,7 +968,7 @@ void ScColumn::CopyFromClip(
 
             ScTokenArray aArr;
             aArr.AddSingleReference( aRef );
-            SetFormulaCell(nDestRow, new ScFormulaCell(pDocument, aDestPos, &aArr));
+            SetFormulaCell(nDestRow, new ScFormulaCell(pDocument, aDestPos, aArr));
         }
 
         return;
@@ -1117,7 +1117,7 @@ public:
                 miNewCellsPos = maNewCells.set(
                     miNewCellsPos, nRow-mnRowOffset,
                     new ScFormulaCell(
-                        &mrDestColumn.GetDoc(), ScAddress(mrDestColumn.GetCol(), nRow, mrDestColumn.GetTab()), &aArr));
+                        &mrDestColumn.GetDoc(), ScAddress(mrDestColumn.GetCol(), nRow, mrDestColumn.GetTab()), aArr));
             }
             break;
             case sc::element_type_string:
@@ -1174,7 +1174,7 @@ public:
                 miNewCellsPos = maNewCells.set(
                     miNewCellsPos, nRow-mnRowOffset,
                     new ScFormulaCell(
-                        &mrDestColumn.GetDoc(), ScAddress(mrDestColumn.GetCol(), nRow, mrDestColumn.GetTab()), &aArr));
+                        &mrDestColumn.GetDoc(), ScAddress(mrDestColumn.GetCol(), nRow, mrDestColumn.GetTab()), aArr));
             }
             break;
             case sc::element_type_formula:
@@ -1203,7 +1203,7 @@ public:
                 miNewCellsPos = maNewCells.set(
                     miNewCellsPos, nRow-mnRowOffset,
                     new ScFormulaCell(
-                        &mrDestColumn.GetDoc(), ScAddress(mrDestColumn.GetCol(), nRow, mrDestColumn.GetTab()), &aArr));
+                        &mrDestColumn.GetDoc(), ScAddress(mrDestColumn.GetCol(), nRow, mrDestColumn.GetTab()), aArr));
             }
             break;
             case sc::element_type_string:
@@ -1282,7 +1282,7 @@ public:
                     miNewCellsPos = maNewCells.set(
                         miNewCellsPos, nDestRow-mnRowOffset,
                         new ScFormulaCell(
-                            &mrDestColumn.GetDoc(), ScAddress(mrDestColumn.GetCol(), nDestRow, mrDestColumn.GetTab()), &aArr));
+                            &mrDestColumn.GetDoc(), ScAddress(mrDestColumn.GetCol(), nDestRow, mrDestColumn.GetTab()), aArr));
                 }
                 break;
                 default:
@@ -1709,7 +1709,7 @@ void ScColumn::SetFormula( SCROW nRow, const ScTokenArray& rArray, formula::Form
     ScAddress aPos(nCol, nRow, nTab);
 
     sc::CellStoreType::iterator it = GetPositionToInsert(nRow);
-    ScFormulaCell* pCell = new ScFormulaCell(pDocument, aPos, &rArray, eGram);
+    ScFormulaCell* pCell = new ScFormulaCell(pDocument, aPos, rArray, eGram);
     sal_uInt32 nCellFormat = GetNumberFormat(nRow);
     if( (nCellFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0)
         pCell->SetNeedNumberFormat(true);
diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx
index c0d6f0d..cd1d2df 100644
--- a/sc/source/core/data/conditio.cxx
+++ b/sc/source/core/data/conditio.cxx
@@ -414,13 +414,13 @@ void ScConditionEntry::MakeCells( const ScAddress& rPos )           // Formelzel
     {
         if ( pFormula1 && !pFCell1 && !bRelRef1 )
         {
-            pFCell1 = new ScFormulaCell( mpDoc, rPos, pFormula1 );
+            pFCell1 = new ScFormulaCell(mpDoc, rPos, *pFormula1);
             pFCell1->StartListeningTo( mpDoc );
         }
 
         if ( pFormula2 && !pFCell2 && !bRelRef2 )
         {
-            pFCell2 = new ScFormulaCell( mpDoc, rPos, pFormula2 );
+            pFCell2 = new ScFormulaCell(mpDoc, rPos, *pFormula2);
             pFCell2->StartListeningTo( mpDoc );
         }
     }
@@ -630,7 +630,7 @@ void ScConditionEntry::Interpret( const ScAddress& rPos )
     ScFormulaCell* pEff1 = pFCell1;
     if ( bRelRef1 )
     {
-        pTemp1 = new ScFormulaCell( mpDoc, rPos, pFormula1 );    // ohne Listening
+        pTemp1 = pFormula1 ? new ScFormulaCell(mpDoc, rPos, *pFormula1) : new ScFormulaCell(mpDoc, rPos);
         pEff1 = pTemp1;
     }
     if ( pEff1 )
@@ -660,7 +660,7 @@ void ScConditionEntry::Interpret( const ScAddress& rPos )
     ScFormulaCell* pEff2 = pFCell2; //@ 1!=2
     if ( bRelRef2 )
     {
-        pTemp2 = new ScFormulaCell( mpDoc, rPos, pFormula2 );    // ohne Listening
+        pTemp2 = pFormula2 ? new ScFormulaCell(mpDoc, rPos, *pFormula2) : new ScFormulaCell(mpDoc, rPos);
         pEff2 = pTemp2;
     }
     if ( pEff2 )
diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx
index 65005bd..0aa6383 100644
--- a/sc/source/core/data/documen4.cxx
+++ b/sc/source/core/data/documen4.cxx
@@ -272,7 +272,7 @@ void ScDocument::InsertMatrixFormula(SCCOL nCol1, SCROW nRow1,
     ScFormulaCell* pCell;
     ScAddress aPos( nCol1, nRow1, nTab1 );
     if (pArr)
-        pCell = new ScFormulaCell( this, aPos, pArr, eGram, MM_FORMULA );
+        pCell = new ScFormulaCell(this, aPos, *pArr, eGram, MM_FORMULA);
     else
         pCell = new ScFormulaCell( this, aPos, rFormula, eGram, MM_FORMULA );
     pCell->SetMatColsRows( nCol2 - nCol1 + 1, nRow2 - nRow1 + 1, bDirtyFlag );
@@ -336,7 +336,7 @@ void ScDocument::InsertMatrixFormula(SCCOL nCol1, SCROW nRow1,
                 aRefData.SetAddress(aBasePos, aPos);
                 t->GetSingleRef() = aRefData;
                 boost::scoped_ptr<ScTokenArray> pTokArr(aArr.Clone());
-                pCell = new ScFormulaCell( this, aPos, pTokArr.get(), eGram, MM_REFERENCE );
+                pCell = new ScFormulaCell(this, aPos, *pTokArr, eGram, MM_REFERENCE);
                 pTab->SetFormulaCell(nCol, nRow, pCell);
             }
         }
diff --git a/sc/source/core/data/documentimport.cxx b/sc/source/core/data/documentimport.cxx
index a5fa521..93b43b0 100644
--- a/sc/source/core/data/documentimport.cxx
+++ b/sc/source/core/data/documentimport.cxx
@@ -216,7 +216,7 @@ void ScDocumentImport::setFormulaCell(const ScAddress& rPos, const ScTokenArray&
 
     sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
     pBlockPos->miCellPos =
-        rCells.set(pBlockPos->miCellPos, rPos.Row(), new ScFormulaCell(&mpImpl->mrDoc, rPos, &rArray));
+        rCells.set(pBlockPos->miCellPos, rPos.Row(), new ScFormulaCell(&mpImpl->mrDoc, rPos, rArray));
 }
 
 void ScDocumentImport::setFormulaCell(const ScAddress& rPos, ScFormulaCell* pCell)
@@ -254,7 +254,7 @@ void ScDocumentImport::setMatrixCells(
     sc::CellStoreType& rCells = pTab->aCol[rBasePos.Col()].maCells;
 
     // Set the master cell.
-    ScFormulaCell* pCell = new ScFormulaCell(&mpImpl->mrDoc, rBasePos, &rArray, eGram, MM_FORMULA);
+    ScFormulaCell* pCell = new ScFormulaCell(&mpImpl->mrDoc, rBasePos, rArray, eGram, MM_FORMULA);
 
     pBlockPos->miCellPos =
         rCells.set(pBlockPos->miCellPos, rBasePos.Row(), pCell);
@@ -283,7 +283,7 @@ void ScDocumentImport::setMatrixCells(
         aRefData.SetAddress(rBasePos, aPos);
         t->GetSingleRef() = aRefData;
         boost::scoped_ptr<ScTokenArray> pTokArr(aArr.Clone());
-        pCell = new ScFormulaCell(&mpImpl->mrDoc, aPos, pTokArr.get(), eGram, MM_REFERENCE);
+        pCell = new ScFormulaCell(&mpImpl->mrDoc, aPos, *pTokArr, eGram, MM_REFERENCE);
         pBlockPos->miCellPos =
             rCells.set(pBlockPos->miCellPos, aPos.Row(), pCell);
     }
@@ -303,7 +303,7 @@ void ScDocumentImport::setMatrixCells(
             aRefData.SetAddress(rBasePos, aPos);
             t->GetSingleRef() = aRefData;
             boost::scoped_ptr<ScTokenArray> pTokArr(aArr.Clone());
-            pCell = new ScFormulaCell(&mpImpl->mrDoc, aPos, pTokArr.get(), eGram, MM_REFERENCE);
+            pCell = new ScFormulaCell(&mpImpl->mrDoc, aPos, *pTokArr, eGram, MM_REFERENCE);
             pBlockPos->miCellPos =
                 rColCells.set(pBlockPos->miCellPos, aPos.Row(), pCell);
         }
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 4f27592..15c3b98 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -429,6 +429,31 @@ void ScFormulaCellGroup::compileCode(
 
 // ============================================================================
 
+ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos ) :
+    eTempGrammar(formula::FormulaGrammar::GRAM_DEFAULT),
+    pCode(new ScTokenArray),
+    pDocument(pDoc),
+    pPrevious(0),
+    pNext(0),
+    pPreviousTrack(0),
+    pNextTrack(0),
+    nSeenInIteration(0),
+    cMatrixFlag(MM_NONE),
+    nFormatType(NUMBERFORMAT_NUMBER),
+    bDirty(false),
+    bChanged(false),
+    bRunning(false),
+    bCompile(false),
+    bSubTotal(false),
+    bIsIterCell(false),
+    bInChangeTrack(false),
+    bTableOpDirty(false),
+    bNeedListening(false),
+    mbNeedsNumberFormat(false),
+    aPos(rPos)
+{
+}
+
 ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
                               const OUString& rFormula,
                               const FormulaGrammar::Grammar eGrammar,
@@ -461,22 +486,20 @@ ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
         pCode = new ScTokenArray;
 }
 
-// Used by import filters
-
-ScFormulaCell::ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
-                              const ScTokenArray* pArr,
-                              const FormulaGrammar::Grammar eGrammar, sal_uInt8 cInd ) :
+ScFormulaCell::ScFormulaCell(
+    ScDocument* pDoc, const ScAddress& rPos, const ScTokenArray& rArray,
+    const FormulaGrammar::Grammar eGrammar, sal_uInt8 cMatInd ) :
     eTempGrammar( eGrammar),
-    pCode( pArr ? new ScTokenArray( *pArr ) : new ScTokenArray ),
+    pCode(new ScTokenArray(rArray)),
     pDocument( pDoc ),
     pPrevious(0),
     pNext(0),
     pPreviousTrack(0),
     pNextTrack(0),
     nSeenInIteration(0),
-    cMatrixFlag ( cInd ),
+    cMatrixFlag ( cMatInd ),
     nFormatType ( NUMBERFORMAT_NUMBER ),
-    bDirty( NULL != pArr ), // -> Because of the use of the Auto Pilot Function was: cInd != 0
+    bDirty( true ),
     bChanged( false ),
     bRunning( false ),
     bCompile( false ),
@@ -2319,7 +2342,10 @@ void setOldCodeToUndo(
     if (pUndoDoc->GetCellType(aUndoPos) == CELLTYPE_FORMULA)
         return;
 
-    ScFormulaCell* pFCell = new ScFormulaCell(pUndoDoc, aUndoPos, pOldCode, eTempGrammar, cMatrixFlag);
+    ScFormulaCell* pFCell =
+        new ScFormulaCell(
+            pUndoDoc, aUndoPos, pOldCode ? *pOldCode : ScTokenArray(), eTempGrammar, cMatrixFlag);
+
     pFCell->SetResultToken(NULL);  // to recognize it as changed later (Cut/Paste!)
     pUndoDoc->SetFormulaCell(aUndoPos, pFCell);
 }
@@ -2919,8 +2945,9 @@ void ScFormulaCell::UpdateTranspose( const ScRange& rSource, const ScAddress& rD
     {
         if (pUndoDoc)
         {
-            ScFormulaCell* pFCell = new ScFormulaCell( pUndoDoc, aPos, pOld,
-                    eTempGrammar, cMatrixFlag);
+            ScFormulaCell* pFCell = new ScFormulaCell(
+                    pUndoDoc, aPos, pOld ? *pOld : ScTokenArray(), eTempGrammar, cMatrixFlag);
+
             pFCell->aResult.SetToken( NULL);  // to recognize it as changed later (Cut/Paste!)
             pUndoDoc->SetFormulaCell(aPos, pFCell);
         }
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index c94d66a..b44122e 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -751,7 +751,7 @@ class TransClipHandler
 
         ScTokenArray aArr;
         aArr.AddSingleReference(aRef);
-        return new ScFormulaCell(&mrClipTab.GetDoc(), rDestPos, &aArr);
+        return new ScFormulaCell(&mrClipTab.GetDoc(), rDestPos, aArr);
     }
 
     void setLink(size_t nRow)
@@ -853,7 +853,7 @@ void ScTable::TransposeClip( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
 
                 pTransClip->SetFormulaCell(
                     static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1),
-                    new ScFormulaCell(pDestDoc, aDestPos, &aArr));
+                    new ScFormulaCell(pDestDoc, aDestPos, aArr));
             }
         }
         else
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index a79add4..99d1c8e 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1056,7 +1056,7 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam )
             aArr.AddOpCode( ocClose );
             aArr.AddOpCode( ocStop );
             ScFormulaCell* pCell = new ScFormulaCell(
-                pDocument, ScAddress(nResCols[nResult], iEntry->nDestRow, nTab), &aArr);
+                pDocument, ScAddress(nResCols[nResult], iEntry->nDestRow, nTab), aArr);
 
             SetFormulaCell(nResCols[nResult], iEntry->nDestRow, pCell);
 
diff --git a/sc/source/core/data/validat.cxx b/sc/source/core/data/validat.cxx
index 5a12649..0adc60a 100644
--- a/sc/source/core/data/validat.cxx
+++ b/sc/source/core/data/validat.cxx
@@ -632,8 +632,8 @@ bool ScValidationData::GetSelectionFromFormula(
     if( NULL == pDocument )
         return false;
 
-    ScFormulaCell aValidationSrc( pDocument, rPos, &rTokArr,
-           formula::FormulaGrammar::GRAM_DEFAULT, MM_FORMULA);
+    ScFormulaCell aValidationSrc(
+        pDocument, rPos, rTokArr, formula::FormulaGrammar::GRAM_DEFAULT, MM_FORMULA);
 
     // Make sure the formula gets interpreted and a result is delivered,
     // regardless of the AutoCalc setting.
diff --git a/sc/source/core/tool/consoli.cxx b/sc/source/core/tool/consoli.cxx
index 25492bb..3dbe8f9 100644
--- a/sc/source/core/tool/consoli.cxx
+++ b/sc/source/core/tool/consoli.cxx
@@ -735,7 +735,7 @@ void ScConsData::OutputToDocument( ScDocument* pDestDoc, SCCOL nCol, SCROW nRow,
                                     aRefArr.AddOpCode(ocStop);
                                     ScAddress aDest( sal::static_int_cast<SCCOL>(nCol+nArrX),
                                                      sal::static_int_cast<SCROW>(nRow+nArrY+nPos), nTab );
-                                    ScFormulaCell* pCell = new ScFormulaCell( pDestDoc, aDest, &aRefArr );
+                                    ScFormulaCell* pCell = new ScFormulaCell(pDestDoc, aDest, aRefArr);
                                     pDestDoc->SetFormulaCell(aDest, pCell);
                                 }
                             }
@@ -755,7 +755,7 @@ void ScConsData::OutputToDocument( ScDocument* pDestDoc, SCCOL nCol, SCROW nRow,
                             aArr.AddDoubleReference(aCRef);
                             aArr.AddOpCode(ocClose);
                             aArr.AddOpCode(ocStop);
-                            ScFormulaCell* pCell = new ScFormulaCell( pDestDoc, aDest, &aArr );
+                            ScFormulaCell* pCell = new ScFormulaCell(pDestDoc, aDest, aArr);
                             pDestDoc->SetFormulaCell(aDest, pCell);
                         }
                     }
diff --git a/sc/source/filter/excel/excform.cxx b/sc/source/filter/excel/excform.cxx
index 74b0ea0..e2e2470 100644
--- a/sc/source/filter/excel/excform.cxx
+++ b/sc/source/filter/excel/excform.cxx
@@ -174,7 +174,7 @@ void ImportExcel::Formula(
 
     if (pResult)
     {
-        pCell = new ScFormulaCell(&rDoc.getDoc(), aScPos, pResult);
+        pCell = new ScFormulaCell(&rDoc.getDoc(), aScPos, *pResult);
         rDoc.getDoc().EnsureTable(aScPos.Tab());
         rDoc.setFormulaCell(aScPos, pCell);
         SetLastFormula(aScPos.Col(), aScPos.Row(), fCurVal, nXF, pCell);
diff --git a/sc/source/filter/excel/impop.cxx b/sc/source/filter/excel/impop.cxx
index b86ea72..8db86c3 100644
--- a/sc/source/filter/excel/impop.cxx
+++ b/sc/source/filter/excel/impop.cxx
@@ -390,7 +390,7 @@ void ImportExcel::ReadBoolErr()
 
         double fValue;
         const ScTokenArray* pScTokArr = ErrorToFormula( nType, nValue, fValue );
-        ScFormulaCell* pCell = new ScFormulaCell( pD, aScPos, pScTokArr );
+        ScFormulaCell* pCell = pScTokArr ? new ScFormulaCell(pD, aScPos, *pScTokArr) : new ScFormulaCell(pD, aScPos);
         pCell->SetHybridDouble( fValue );
         GetDoc().SetFormulaCell(aScPos, pCell);
     }
diff --git a/sc/source/filter/excel/xipivot.cxx b/sc/source/filter/excel/xipivot.cxx
index 99ceb86..30af343 100644
--- a/sc/source/filter/excel/xipivot.cxx
+++ b/sc/source/filter/excel/xipivot.cxx
@@ -121,7 +121,7 @@ void XclImpPCItem::WriteToSource( XclImpRoot& rRoot, const ScAddress& rScPos ) c
         sal_uInt8 nErrCode = static_cast< sal_uInt8 >( *pnError );
         const ScTokenArray* pScTokArr = rRoot.GetOldFmlaConverter().GetBoolErr(
             XclTools::ErrorToEnum( fValue, EXC_BOOLERR_ERROR, nErrCode ) );
-        ScFormulaCell* pCell = new ScFormulaCell(&rDoc.getDoc(), rScPos, pScTokArr);
+        ScFormulaCell* pCell = pScTokArr ? new ScFormulaCell(&rDoc.getDoc(), rScPos, *pScTokArr) : new ScFormulaCell(&rDoc.getDoc(), rScPos);
         pCell->SetHybridDouble( fValue );
         rDoc.setFormulaCell(rScPos, pCell);
     }
diff --git a/sc/source/filter/lotus/lotimpop.cxx b/sc/source/filter/lotus/lotimpop.cxx
index ad27360..f8fc773 100644
--- a/sc/source/filter/lotus/lotimpop.cxx
+++ b/sc/source/filter/lotus/lotimpop.cxx
@@ -290,7 +290,7 @@ ScFormulaCell *ImportLotus::Formulacell( sal_uInt16 n )
     aConv.SetWK3();
     aConv.Convert( pErg, nRest );
 
-    ScFormulaCell* pCell = new ScFormulaCell( pD, aAddr, pErg );
+    ScFormulaCell* pCell = pErg ? new ScFormulaCell(pD, aAddr, *pErg) : new ScFormulaCell(pD, aAddr);
     pCell->AddRecalcMode( RECALCMODE_ONLOAD_ONCE );
     pD->EnsureTable(aAddr.Tab());
     pD->SetFormulaCell(aAddr, pCell);
diff --git a/sc/source/filter/lotus/op.cxx b/sc/source/filter/lotus/op.cxx
index 9e777a7..c42211d 100644
--- a/sc/source/filter/lotus/op.cxx
+++ b/sc/source/filter/lotus/op.cxx
@@ -169,7 +169,7 @@ void OP_Formula( SvStream& r, sal_uInt16 /*n*/ )
 
     if (ValidColRow( static_cast<SCCOL>(nCol), nRow))
     {
-        ScFormulaCell* pCell = new ScFormulaCell( pLotusRoot->pDoc, aAddress, pErg );
+        ScFormulaCell* pCell = new ScFormulaCell(pLotusRoot->pDoc, aAddress, *pErg);
         pCell->AddRecalcMode( RECALCMODE_ONLOAD_ONCE );
         pDoc->EnsureTable(nTab);
         pDoc->SetFormulaCell(ScAddress(nCol,nRow,nTab), pCell);
@@ -413,7 +413,7 @@ void OP_Formula123( SvStream& r, sal_uInt16 n )
 
     if (ValidColRow( static_cast<SCCOL>(nCol), nRow) && nTab <= pDoc->GetMaxTableNumber())
     {
-        ScFormulaCell* pCell = new ScFormulaCell( pLotusRoot->pDoc, aAddress, pErg );
+        ScFormulaCell* pCell = new ScFormulaCell(pLotusRoot->pDoc, aAddress, *pErg);
         pCell->AddRecalcMode( RECALCMODE_ONLOAD_ONCE );
         pDoc->EnsureTable(nTab);
         pDoc->SetFormulaCell(ScAddress(nCol,nRow,nTab), pCell);
diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx
index cf5b73e..3dde87b 100644
--- a/sc/source/filter/oox/formulabuffer.cxx
+++ b/sc/source/filter/oox/formulabuffer.cxx
@@ -173,7 +173,7 @@ void FormulaBuffer::applySharedFormulas( sal_Int32 nTab )
 
             ScAddress aPos;
             ScUnoConversion::FillScAddress(aPos, rAddr);
-            ScFormulaCell* pCell = new ScFormulaCell(&rDoc.getDoc(), aPos, pArray);
+            ScFormulaCell* pCell = new ScFormulaCell(&rDoc.getDoc(), aPos, *pArray);
             rDoc.setFormulaCell(aPos, pCell);
             if (it->maCellValue.isEmpty())
             {
diff --git a/sc/source/filter/orcus/interface.cxx b/sc/source/filter/orcus/interface.cxx
index 1372d775..df8c992 100644
--- a/sc/source/filter/orcus/interface.cxx
+++ b/sc/source/filter/orcus/interface.cxx
@@ -358,7 +358,7 @@ void ScOrcusSheet::set_shared_formula(
 
     maFormulaGroups.set(sindex, pArray);
 
-    ScFormulaCell* pCell = new ScFormulaCell(&mrDoc.getDoc(), aPos, pArray);
+    ScFormulaCell* pCell = new ScFormulaCell(&mrDoc.getDoc(), aPos, *pArray);
     mrDoc.setFormulaCell(aPos, pCell);
     cellInserted();
 
@@ -381,7 +381,7 @@ void ScOrcusSheet::set_shared_formula(os::row_t row, os::col_t col, size_t sinde
     if (!pArray)
         return;
 
-    ScFormulaCell* pCell = new ScFormulaCell(&mrDoc.getDoc(), aPos, pArray);
+    ScFormulaCell* pCell = new ScFormulaCell(&mrDoc.getDoc(), aPos, *pArray);
     mrDoc.setFormulaCell(aPos, pCell);
     cellInserted();
 
diff --git a/sc/source/filter/qpro/qpro.cxx b/sc/source/filter/qpro/qpro.cxx
index bff702b..77dc5dca 100644
--- a/sc/source/filter/qpro/qpro.cxx
+++ b/sc/source/filter/qpro/qpro.cxx
@@ -110,7 +110,7 @@ FltError ScQProReader::readSheet( SCTAB nTab, ScDocument* pDoc, ScQProStyle *pSt
                     eRet = eERR_FORMAT;
                 else
                 {
-                    ScFormulaCell *pFormula = new ScFormulaCell( pDoc, aAddr, pArray );
+                    ScFormulaCell* pFormula = new ScFormulaCell(pDoc, aAddr, *pArray);
                     nStyle = nStyle >> 3;
                     pFormula->AddRecalcMode( RECALCMODE_ONLOAD_ONCE );
                     pStyle->SetFormat( pDoc, nCol, nRow, nTab, nStyle );
diff --git a/sc/source/filter/xcl97/XclImpChangeTrack.cxx b/sc/source/filter/xcl97/XclImpChangeTrack.cxx
index a2f1dde..4892861 100644
--- a/sc/source/filter/xcl97/XclImpChangeTrack.cxx
+++ b/sc/source/filter/xcl97/XclImpChangeTrack.cxx
@@ -272,7 +272,7 @@ void XclImpChangeTrack::ReadCell(
             if( pStrm->IsValid() && pTokenArray )
             {
                 rCell.meType = CELLTYPE_FORMULA;
-                rCell.mpFormula = new ScFormulaCell(GetDocPtr(), rPosition, pTokenArray);
+                rCell.mpFormula = new ScFormulaCell(GetDocPtr(), rPosition, *pTokenArray);
             }
             delete pTokenArray;
         }

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list