[Libreoffice-commits] core.git: 7 commits - formula/source include/formula include/svl sc/inc sc/Library_sc.mk sc/qa sc/source svl/Library_svl.mk svl/source

Kohei Yoshida kohei.yoshida at collabora.com
Thu Nov 14 20:52:41 PST 2013


 formula/source/core/api/FormulaCompiler.cxx |   22 +-
 include/formula/FormulaCompiler.hxx         |   21 +-
 include/svl/broadcast.hxx                   |   36 +++-
 include/svl/listener.hxx                    |   28 +--
 include/svl/listeneriter.hxx                |   65 --------
 sc/Library_sc.mk                            |    1 
 sc/inc/compiler.hxx                         |   23 +--
 sc/inc/document.hxx                         |    2 
 sc/inc/pch/precompiled_sc.hxx               |    1 
 sc/inc/tokenarray.hxx                       |    7 
 sc/inc/tokenstringcontext.hxx               |   39 +++++
 sc/qa/unit/ucalc.hxx                        |    2 
 sc/qa/unit/ucalc_formula.cxx                |   31 ++++
 sc/source/core/data/bcaslot.cxx             |   10 -
 sc/source/core/data/column2.cxx             |   11 -
 sc/source/core/data/document.cxx            |   16 ++
 sc/source/core/tool/compiler.cxx            |  211 ++++++++++++++++------------
 sc/source/core/tool/token.cxx               |  158 ++++++++++++++++++++
 sc/source/core/tool/tokenstringcontext.cxx  |   29 +++
 sc/source/filter/oox/formulabuffer.cxx      |   87 ++++++-----
 svl/Library_svl.mk                          |    2 
 svl/source/notify/broadcast.cxx             |  129 ++++++++++-------
 svl/source/notify/listener.cxx              |  115 ++++-----------
 svl/source/notify/listenerbase.cxx          |   66 --------
 svl/source/notify/listenerbase.hxx          |   50 ------
 svl/source/notify/listeneriter.cxx          |  105 -------------
 26 files changed, 650 insertions(+), 617 deletions(-)

New commits:
commit 07f8216e5722d2288143367a07f4d567ab060431
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Nov 14 21:20:12 2013 -0500

    Create string from token array directly from ScTokenArray. Still WIP.
    
    And make it re-entrant for thread safety. This method should not modify
    the internal state of the token array object. The one with ScCompiler
    is not re-entrant. Still some way to go.
    
    Change-Id: I06de3637341727aef0963dddfb98527f415bf7fa

diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 5754ad9..c9f0b5f 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -254,6 +254,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/core/tool/stylehelper \
     sc/source/core/tool/subtotal \
     sc/source/core/tool/token \
+    sc/source/core/tool/tokenstringcontext \
     sc/source/core/tool/typedstrdata \
     sc/source/core/tool/unitconv \
     sc/source/core/tool/userlist \
diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx
index 4cd31a3..6844b28 100644
--- a/sc/inc/compiler.hxx
+++ b/sc/inc/compiler.hxx
@@ -234,10 +234,11 @@ public:
         Convention( formula::FormulaGrammar::AddressConvention eConvP );
         virtual ~Convention();
 
-        virtual void MakeRefStr( OUStringBuffer&   rBuffer,
-                                 const ScCompiler&      rCompiler,
-                                 const ScComplexRefData&    rRef,
-                                 bool bSingleRef ) const = 0;
+        virtual void makeRefStr(
+            OUStringBuffer& rBuffer, const ScAddress& rPos, formula::FormulaGrammar::Grammar eGram,
+            const OUString& rErrRef, const std::vector<OUString>& rTabNames,
+            const ScComplexRefData& rRef, bool bSingleRef ) const = 0;
+
         virtual ::com::sun::star::i18n::ParseResult
                     parseAnyToken( const OUString& rFormula,
                                    sal_Int32 nSrcPos,
@@ -397,6 +398,8 @@ public:
     void            SetRefConvention( const Convention *pConvP );
     void            SetRefConvention( const formula::FormulaGrammar::AddressConvention eConv );
 
+    static const Convention* GetRefConvention( formula::FormulaGrammar::AddressConvention eConv );
+
     /// Set symbol map if not empty.
     void            SetFormulaLanguage( const OpCodeMapPtr & xMap );
 
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 09f1466..68e57d2 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -555,6 +555,8 @@ public:
     SC_DLLPUBLIC bool SetCodeName( SCTAB nTab, const OUString& rName );
     SC_DLLPUBLIC bool GetTable( const OUString& rName, SCTAB& rTab ) const;
 
+    std::vector<OUString> GetAllTableNames() const;
+
     OUString   GetCopyTabName(SCTAB nTab) const;
 
     SC_DLLPUBLIC void SetAnonymousDBData(SCTAB nTab, ScDBData* pDBData);
diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index 83a3988..b8aec07 100644
--- a/sc/inc/tokenarray.hxx
+++ b/sc/inc/tokenarray.hxx
@@ -36,6 +36,7 @@ struct RefUpdateInsertTabContext;
 struct RefUpdateDeleteTabContext;
 struct RefUpdateMoveTabContext;
 struct RefUpdateResult;
+struct TokenStringContext;
 
 }
 
@@ -171,6 +172,12 @@ public:
     void CheckRelativeReferenceBounds(
         const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen, std::vector<SCROW>& rBounds ) const;
 
+    /**
+     * Create a string representation of formula token array without modifying
+     * the internal state of the token array.
+     */
+    OUString CreateString( sc::TokenStringContext& rCxt, const ScAddress& rPos ) const;
+
 #if DEBUG_FORMULA_COMPILER
     void Dump() const;
 #endif
diff --git a/sc/inc/tokenstringcontext.hxx b/sc/inc/tokenstringcontext.hxx
new file mode 100644
index 0000000..e5bb01c
--- /dev/null
+++ b/sc/inc/tokenstringcontext.hxx
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef SC_TOKENSTRINGCONTEXT_HXX
+#define SC_TOKENSTRINGCONTEXT_HXX
+
+#include "compiler.hxx"
+
+namespace sc {
+
+/**
+ * Context for creating string from an array of formula tokens, used in
+ * ScTokenArray::CreateString().  You can re-use the same string context
+ * between multiple CreateString() calls as long as the document content is
+ * unmodified.
+ */
+struct TokenStringContext
+{
+    formula::FormulaGrammar::Grammar meGram;
+    formula::FormulaCompiler::OpCodeMapPtr mxOpCodeMap;
+    const ScCompiler::Convention* mpRefConv;
+    OUString maErrRef;
+
+    std::vector<OUString> maTabNames;
+
+    TokenStringContext( formula::FormulaGrammar::Grammar eGram );
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx
index 19c94d7..1298e73 100644
--- a/sc/qa/unit/ucalc.hxx
+++ b/sc/qa/unit/ucalc.hxx
@@ -84,6 +84,7 @@ public:
     void testRangeList();
     void testInput();
 
+    void testFormulaCreateStringFromTokens();
     void testFormulaParseReference();
     void testFetchVectorRefArray();
     void testFormulaHashAndTag();
@@ -293,6 +294,7 @@ public:
     CPPUNIT_TEST(testSharedStringPool);
     CPPUNIT_TEST(testRangeList);
     CPPUNIT_TEST(testInput);
+    CPPUNIT_TEST(testFormulaCreateStringFromTokens);
     CPPUNIT_TEST(testFormulaParseReference);
     CPPUNIT_TEST(testFetchVectorRefArray);
     CPPUNIT_TEST(testFormulaHashAndTag);
diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index d12e45d..c780717 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -22,6 +22,7 @@
 #include "docsh.hxx"
 #include "docfunc.hxx"
 #include "paramisc.hxx"
+#include "tokenstringcontext.hxx"
 
 #include "formula/vectortoken.hxx"
 
@@ -29,6 +30,36 @@
 
 using namespace formula;
 
+void Test::testFormulaCreateStringFromTokens()
+{
+    m_pDoc->InsertTab(0, "Test");
+
+    const char* aTests[] = {
+        "1+2",
+        "SUM(A1:A10;B1:B10;C5;D6)"
+    };
+
+    boost::scoped_ptr<ScTokenArray> pArray;
+
+    sc::TokenStringContext aCxt(formula::FormulaGrammar::GRAM_ENGLISH);
+    aCxt.maTabNames = m_pDoc->GetAllTableNames();
+    ScAddress aPos(0,0,0);
+
+    for (size_t i = 0, n = SAL_N_ELEMENTS(aTests); i < n; ++i)
+    {
+        OUString aFormula = OUString::createFromAscii(aTests[i]);
+        ScCompiler aComp(m_pDoc, aPos);
+        aComp.SetGrammar(FormulaGrammar::GRAM_ENGLISH);
+        pArray.reset(aComp.CompileString(aFormula));
+        CPPUNIT_ASSERT_MESSAGE("Failed to compile formula string.", pArray.get());
+
+        OUString aCheck = pArray->CreateString(aCxt, aPos);
+        CPPUNIT_ASSERT_EQUAL(aFormula, aCheck);
+    }
+
+    m_pDoc->DeleteTab(0);
+}
+
 namespace {
 
 bool isEmpty( const formula::VectorRefArray& rArray, size_t nPos )
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index f8a6d92..80696e4 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -251,6 +251,22 @@ bool ScDocument::GetTable( const OUString& rName, SCTAB& rTab ) const
     return false;
 }
 
+std::vector<OUString> ScDocument::GetAllTableNames() const
+{
+    std::vector<OUString> aNames;
+    aNames.reserve(maTabs.size());
+    TableContainer::const_iterator it = maTabs.begin(), itEnd = maTabs.end();
+    for (; it != itEnd; ++it)
+    {
+        OUString aName;
+        const ScTable& rTab = **it;
+        rTab.GetName(aName);
+        aNames.push_back(aName);
+    }
+
+    return aNames;
+}
+
 ScDBData* ScDocument::GetAnonymousDBData(SCTAB nTab)
 {
     if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 6641451..1ef766c 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -726,15 +726,15 @@ struct ConventionOOO_A1 : public Convention_A1
 {
     ConventionOOO_A1() : Convention_A1 (FormulaGrammar::CONV_OOO) { }
     ConventionOOO_A1( FormulaGrammar::AddressConvention eConv ) : Convention_A1 (eConv) { }
-    static OUString MakeTabStr( const ScCompiler& rComp, SCTAB nTab, OUString& aDoc )
+
+    static OUString MakeTabStr( const std::vector<OUString>& rTabNames, SCTAB nTab, OUString& aDoc )
     {
         OUString aString;
-        OUString aTmp;
-        if (!rComp.GetDoc()->GetName( nTab, aTmp ))
+        if (static_cast<size_t>(nTab) >= rTabNames.size())
             aString = ScGlobal::GetRscString(STR_NO_REF_TABLE);
         else
         {
-            aString = aTmp;
+            aString = rTabNames[nTab];
             // "'Doc'#Tab"
             sal_Int32 nPos = ScCompiler::GetDocTabPos( aString );
             if ( nPos != -1 )
@@ -753,7 +753,7 @@ struct ConventionOOO_A1 : public Convention_A1
     }
 
     void MakeOneRefStrImpl(
-        OUStringBuffer& rBuffer, const ScCompiler& rComp,
+        OUStringBuffer& rBuffer, const OUString& rErrRef, const std::vector<OUString>& rTabNames,
         const ScSingleRefData& rRef, const ScAddress& rAbsRef,
         bool bForceTab, bool bODF ) const
     {
@@ -763,13 +763,13 @@ struct ConventionOOO_A1 : public Convention_A1
             {
                 if (!rRef.IsTabRel())
                     rBuffer.append('$');
-                rBuffer.append( rComp.GetCurrentOpCodeMap()->getSymbol( ocErrRef));
+                rBuffer.append(rErrRef);
                 rBuffer.append('.');
             }
             else
             {
                 OUString aDoc;
-                OUString aRefStr(MakeTabStr(rComp, rAbsRef.Tab(), aDoc));
+                OUString aRefStr(MakeTabStr(rTabNames, rAbsRef.Tab(), aDoc));
                 rBuffer.append(aDoc);
                 if (!rRef.IsTabRel())
                     rBuffer.append('$');
@@ -781,58 +781,38 @@ struct ConventionOOO_A1 : public Convention_A1
         if (!rRef.IsColRel())
             rBuffer.append('$');
         if (!ValidCol(rAbsRef.Col()))
-            rBuffer.append( rComp.GetCurrentOpCodeMap()->getSymbol( ocErrRef));
+            rBuffer.append(rErrRef);
         else
             MakeColStr(rBuffer, rAbsRef.Col());
         if (!rRef.IsRowRel())
             rBuffer.append('$');
         if (!ValidRow(rAbsRef.Row()))
-            rBuffer.append( rComp.GetCurrentOpCodeMap()->getSymbol( ocErrRef));
+            rBuffer.append(rErrRef);
         else
             MakeRowStr(rBuffer, rAbsRef.Row());
     }
 
-    void MakeRefStrImpl( OUStringBuffer&   rBuffer,
-                         const ScCompiler&      rComp,
-                         const ScComplexRefData&    rRef,
-                         bool bSingleRef,
-                         bool bODF ) const
+    void makeRefStr( OUStringBuffer&   rBuffer,
+                     const ScAddress& rPos,
+                     FormulaGrammar::Grammar /*eGram*/,
+                     const OUString& rErrRef,
+                     const std::vector<OUString>& rTabNames,
+                     const ScComplexRefData& rRef,
+                     bool bSingleRef ) const
     {
-        if (bODF)
-            rBuffer.append('[');
         ScComplexRefData aRef( rRef );
         // In case absolute/relative positions weren't separately available:
         // transform relative to absolute!
-        ScAddress aAbs1 = aRef.Ref1.toAbs(rComp.GetPos()), aAbs2;
+        ScAddress aAbs1 = aRef.Ref1.toAbs(rPos), aAbs2;
         if( !bSingleRef )
-            aAbs2 = aRef.Ref2.toAbs(rComp.GetPos());
+            aAbs2 = aRef.Ref2.toAbs(rPos);
 
-        if (bODF && FormulaGrammar::isODFF( rComp.GetGrammar()) && (!ValidAddress(aAbs1) || !ValidAddress(aAbs2)))
-        {
-            rBuffer.append( rComp.GetCurrentOpCodeMap()->getSymbol( ocErrRef));
-            // For ODFF write [#REF!], but not for PODF so apps reading ODF
-            // 1.0/1.1 may have a better chance if they implemented the old
-            // form.
-        }
-        else
+        MakeOneRefStrImpl(rBuffer, rErrRef, rTabNames, aRef.Ref1, aAbs1, false, false);
+        if (!bSingleRef)
         {
-            MakeOneRefStrImpl(rBuffer, rComp, aRef.Ref1, aAbs1, false, bODF);
-            if (!bSingleRef)
-            {
-                rBuffer.append(':');
-                MakeOneRefStrImpl(rBuffer, rComp, aRef.Ref2, aAbs2, aAbs1.Tab() != aAbs2.Tab(), bODF);
-            }
+            rBuffer.append(':');
+            MakeOneRefStrImpl(rBuffer, rErrRef, rTabNames, aRef.Ref2, aAbs2, aAbs1.Tab() != aAbs2.Tab(), false);
         }
-        if (bODF)
-            rBuffer.append(']');
-    }
-
-    void MakeRefStr( OUStringBuffer&   rBuffer,
-                     const ScCompiler&      rComp,
-                     const ScComplexRefData& rRef,
-                     bool bSingleRef ) const
-    {
-        MakeRefStrImpl( rBuffer, rComp, rRef, bSingleRef, false);
     }
 
     virtual sal_Unicode getSpecialSymbol( SpecialSymbolType eSymType ) const
@@ -1005,12 +985,39 @@ const ScCompiler::Convention * const ScCompiler::pConvOOO_A1 = &ConvOOO_A1;
 struct ConventionOOO_A1_ODF : public ConventionOOO_A1
 {
     ConventionOOO_A1_ODF() : ConventionOOO_A1 (FormulaGrammar::CONV_ODF) { }
-    void MakeRefStr( OUStringBuffer&   rBuffer,
-                     const ScCompiler&      rComp,
+    void makeRefStr( OUStringBuffer&   rBuffer,
+                     const ScAddress& rPos,
+                     FormulaGrammar::Grammar eGram,
+                     const OUString& rErrRef,
+                     const std::vector<OUString>& rTabNames,
                      const ScComplexRefData& rRef,
                      bool bSingleRef ) const
     {
-        MakeRefStrImpl( rBuffer, rComp, rRef, bSingleRef, true);
+        rBuffer.append(sal_Unicode('['));
+        ScComplexRefData aRef( rRef );
+        // In case absolute/relative positions weren't separately available:
+        // transform relative to absolute!
+        ScAddress aAbs1 = aRef.Ref1.toAbs(rPos), aAbs2;
+        if( !bSingleRef )
+            aAbs2 = aRef.Ref2.toAbs(rPos);
+
+        if (FormulaGrammar::isODFF(eGram) && (!ValidAddress(aAbs1) || !ValidAddress(aAbs2)))
+        {
+            rBuffer.append(rErrRef);
+            // For ODFF write [#REF!], but not for PODF so apps reading ODF
+            // 1.0/1.1 may have a better chance if they implemented the old
+            // form.
+        }
+        else
+        {
+            MakeOneRefStrImpl(rBuffer, rErrRef, rTabNames, aRef.Ref1, aAbs1, false, true);
+            if (!bSingleRef)
+            {
+                rBuffer.append(sal_Unicode(':'));
+                MakeOneRefStrImpl(rBuffer, rErrRef, rTabNames, aRef.Ref2, aAbs2, aAbs1.Tab() != aAbs2.Tab(), true);
+            }
+        }
+        rBuffer.append(sal_Unicode(']'));
     }
 
     virtual OUString makeExternalNameStr( const OUString& rFile, const OUString& rName ) const
@@ -1038,22 +1045,20 @@ const ScCompiler::Convention * const ScCompiler::pConvOOO_A1_ODF = &ConvOOO_A1_O
 
 struct ConventionXL
 {
-    static bool GetDocAndTab( const ScCompiler& rComp,
-                              const ScSingleRefData& rRef,
-                              OUString& rDocName,
-                              OUString& rTabName )
+    static bool GetDocAndTab(
+        const ScAddress& rPos, const std::vector<OUString>& rTabNames,
+        const ScSingleRefData& rRef, OUString& rDocName, OUString& rTabName )
     {
         bool bHasDoc = false;
 
         rDocName = "";
-        OUString aTmp;
-        ScAddress aAbs = rRef.toAbs(rComp.GetPos());
-        if (rRef.IsTabDeleted() || !rComp.GetDoc()->GetName(aAbs.Tab(), aTmp))
+        ScAddress aAbs = rRef.toAbs(rPos);
+        if (rRef.IsTabDeleted() || static_cast<size_t>(aAbs.Tab()) >= rTabNames.size())
         {
             rTabName = ScGlobal::GetRscString( STR_NO_REF_TABLE );
             return false;
         }
-        rTabName = aTmp;
+        rTabName = rTabNames[aAbs.Tab()];
 
         // Cheesy hack to unparse the OOO style "'Doc'#Tab"
         sal_Int32 nPos = ScCompiler::GetDocTabPos( rTabName);
@@ -1074,7 +1079,8 @@ struct ConventionXL
     }
 
     static void MakeDocStr( OUStringBuffer& rBuf,
-                            const ScCompiler& rComp,
+                            const ScAddress& rPos,
+                            const std::vector<OUString>& rTabNames,
                             const ScComplexRefData& rRef,
                             bool bSingleRef )
     {
@@ -1083,13 +1089,13 @@ struct ConventionXL
             OUString aStartTabName, aStartDocName, aEndTabName, aEndDocName;
             bool bStartHasDoc = false, bEndHasDoc = false;
 
-            bStartHasDoc = GetDocAndTab( rComp, rRef.Ref1,
-                                         aStartDocName, aStartTabName);
+            bStartHasDoc = GetDocAndTab(
+                rPos, rTabNames, rRef.Ref1, aStartDocName, aStartTabName);
 
             if( !bSingleRef && rRef.Ref2.IsFlag3D() )
             {
-                bEndHasDoc = GetDocAndTab( rComp, rRef.Ref2,
-                                           aEndDocName, aEndTabName);
+                bEndHasDoc = GetDocAndTab(
+                    rPos, rTabNames, rRef.Ref2, aEndDocName, aEndTabName);
             }
             else
                 bEndHasDoc = bStartHasDoc;
@@ -1259,8 +1265,11 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
         MakeRowStr(rBuf, rAbs.Row());
     }
 
-    void MakeRefStr( OUStringBuffer&   rBuf,
-                     const ScCompiler&      rComp,
+    void makeRefStr( OUStringBuffer&   rBuf,
+                     const ScAddress& rPos,
+                     FormulaGrammar::Grammar /*eGram*/,
+                     const OUString& /*rErrRef*/,
+                     const std::vector<OUString>& rTabNames,
                      const ScComplexRefData& rRef,
                      bool bSingleRef ) const
     {
@@ -1268,9 +1277,9 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
 
         // Play fast and loose with invalid refs.  There is not much point in producing
         // Foo!A1:#REF! versus #REF! at this point
-        ScAddress aAbs1 = aRef.Ref1.toAbs(rComp.GetPos()), aAbs2;
+        ScAddress aAbs1 = aRef.Ref1.toAbs(rPos), aAbs2;
 
-        MakeDocStr( rBuf, rComp, aRef, bSingleRef );
+        MakeDocStr(rBuf, rPos, rTabNames, aRef, bSingleRef);
 
         if (!ValidAddress(aAbs1))
         {
@@ -1280,7 +1289,7 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
 
         if( !bSingleRef )
         {
-            aAbs2 = aRef.Ref2.toAbs(rComp.GetPos());
+            aAbs2 = aRef.Ref2.toAbs(rPos);
             if (!ValidAddress(aAbs2))
             {
                 rBuf.append(ScGlobal::GetRscString(STR_NO_REF_TABLE));
@@ -1448,15 +1457,18 @@ r1c1_add_row( OUStringBuffer &rBuf, const ScSingleRefData& rRef, const ScAddress
 struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
 {
     ConventionXL_R1C1() : ScCompiler::Convention( FormulaGrammar::CONV_XL_R1C1 ) { }
-    void MakeRefStr( OUStringBuffer&   rBuf,
-                     const ScCompiler&      rComp,
+    void makeRefStr( OUStringBuffer&   rBuf,
+                     const ScAddress& rPos,
+                     FormulaGrammar::Grammar /*eGram*/,
+                     const OUString& /*rErrRef*/,
+                     const std::vector<OUString>& rTabNames,
                      const ScComplexRefData& rRef,
                      bool bSingleRef ) const
     {
-        ScRange aAbsRef = rRef.toAbs(rComp.GetPos());
+        ScRange aAbsRef = rRef.toAbs(rPos);
         ScComplexRefData aRef( rRef );
 
-        MakeDocStr( rBuf, rComp, aRef, bSingleRef );
+        MakeDocStr(rBuf, rPos, rTabNames, aRef, bSingleRef);
 
         // Play fast and loose with invalid refs.  There is not much point in producing
         // Foo!A1:#REF! versus #REF! at this point
@@ -1662,7 +1674,7 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos)
         :
         pDoc( pDocument ),
         aPos( rPos ),
-        mpFormatter(pDoc->GetFormatTable()),
+        mpFormatter(pDoc ? pDoc->GetFormatTable() : NULL),
         pCharClass( ScGlobal::pCharClass ),
         mnPredetectedReference(0),
         mnRangeOpPosInSymbol(-1),
@@ -1729,16 +1741,31 @@ sal_Int32 ScCompiler::GetDocTabPos( const OUString& rString )
 
 void ScCompiler::SetRefConvention( FormulaGrammar::AddressConvention eConv )
 {
-    switch ( eConv ) {
-        case FormulaGrammar::CONV_UNSPECIFIED :
-            break;
-        default :
-        case FormulaGrammar::CONV_OOO :      SetRefConvention( pConvOOO_A1 ); break;
-        case FormulaGrammar::CONV_ODF :      SetRefConvention( pConvOOO_A1_ODF ); break;
-        case FormulaGrammar::CONV_XL_A1 :    SetRefConvention( pConvXL_A1 );  break;
-        case FormulaGrammar::CONV_XL_R1C1 :  SetRefConvention( pConvXL_R1C1 ); break;
-        case FormulaGrammar::CONV_XL_OOX :   SetRefConvention( pConvXL_OOX ); break;
+    const Convention* p = GetRefConvention(eConv);
+    if (p)
+        SetRefConvention(p);
+}
+
+const ScCompiler::Convention* ScCompiler::GetRefConvention( FormulaGrammar::AddressConvention eConv )
+{
+    switch (eConv)
+    {
+        case FormulaGrammar::CONV_OOO:
+            return pConvOOO_A1;
+        case FormulaGrammar::CONV_ODF:
+            return pConvOOO_A1_ODF;
+        case FormulaGrammar::CONV_XL_A1:
+            return pConvXL_A1;
+        case FormulaGrammar::CONV_XL_R1C1:
+            return pConvXL_R1C1;
+        case FormulaGrammar::CONV_XL_OOX:
+            return pConvXL_OOX;
+        case FormulaGrammar::CONV_UNSPECIFIED:
+        default:
+            ;
     }
+
+    return NULL;
 }
 
 void ScCompiler::SetRefConvention( const ScCompiler::Convention *pConvP )
@@ -4201,6 +4228,8 @@ void ScCompiler::CreateStringFromSingleRef(OUStringBuffer& rBuffer,FormulaToken*
     const ScSingleRefData& rRef = static_cast<const ScToken*>(_pTokenP)->GetSingleRef();
     ScComplexRefData aRef;
     aRef.Ref1 = aRef.Ref2 = rRef;
+    OUString aErrRef = GetCurrentOpCodeMap()->getSymbol( ocErrRef);
+    std::vector<OUString> aTabNames = GetDoc()->GetAllTableNames();
     if ( eOp == ocColRowName )
     {
         ScAddress aAbs = rRef.toAbs(aPos);
@@ -4213,16 +4242,18 @@ void ScCompiler::CreateStringFromSingleRef(OUStringBuffer& rBuffer,FormulaToken*
         else
         {
             rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
-            pConv->MakeRefStr (rBuffer, *this, aRef, true );
+            pConv->makeRefStr(rBuffer, aPos, meGrammar, aErrRef, aTabNames, aRef, true);
         }
     }
     else
-        pConv->MakeRefStr( rBuffer, *this, aRef, true );
+        pConv->makeRefStr(rBuffer, aPos, meGrammar, aErrRef, aTabNames, aRef, true);
 }
 
 void ScCompiler::CreateStringFromDoubleRef(OUStringBuffer& rBuffer,FormulaToken* _pTokenP) const
 {
-    pConv->MakeRefStr( rBuffer, *this, static_cast<ScToken*>(_pTokenP)->GetDoubleRef(), false );
+    OUString aErrRef = GetCurrentOpCodeMap()->getSymbol( ocErrRef);
+    std::vector<OUString> aTabNames = GetDoc()->GetAllTableNames();
+    pConv->makeRefStr(rBuffer, aPos, meGrammar, aErrRef, aTabNames, static_cast<ScToken*>(_pTokenP)->GetDoubleRef(), false);
 }
 
 void ScCompiler::CreateStringFromIndex(OUStringBuffer& rBuffer,FormulaToken* _pTokenP) const
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 3d99294..c9377a2 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -38,6 +38,7 @@
 #include "externalrefmgr.hxx"
 #include "document.hxx"
 #include "refupdatecontext.hxx"
+#include "tokenstringcontext.hxx"
 #include "types.hxx"
 #include "svl/sharedstring.hxx"
 
@@ -3165,6 +3166,163 @@ void ScTokenArray::CheckRelativeReferenceBounds(
     }
 }
 
+namespace {
+
+void appendTokenByType( sc::TokenStringContext& rCxt, OUStringBuffer& rBuf, const FormulaToken& rToken, const ScAddress& rPos )
+{
+    if (rToken.IsExternalRef())
+    {
+        // TODO : Implement this.
+        return;
+    }
+
+    OpCode eOp = rToken.GetOpCode();
+    switch (rToken.GetType())
+    {
+        case svDouble:
+        {
+            if (rCxt.mxOpCodeMap->isEnglish())
+            {
+                rtl::math::doubleToUStringBuffer(
+                    rBuf, rToken.GetDouble(), rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
+            }
+            else
+            {
+                SvtSysLocale aSysLocale;
+                rtl::math::doubleToUStringBuffer(
+                    rBuf, rToken.GetDouble(),
+                    rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
+                    aSysLocale.GetLocaleDataPtr()->getNumDecimalSep()[0], true);
+            }
+        }
+        break;
+        case svString:
+        {
+            OUString aStr = rToken.GetString().getString();
+            if (eOp == ocBad || eOp == ocStringXML)
+            {
+                rBuf.append(aStr);
+                return;
+            }
+
+            rBuf.append(sal_Unicode('"'));
+            rBuf.append(aStr.replaceAll("\"", "\"\""));
+            rBuf.append(sal_Unicode('"'));
+        }
+        break;
+        case svSingleRef:
+        {
+            if (rCxt.mpRefConv)
+            {
+                const ScSingleRefData& rRef = static_cast<const ScToken&>(rToken).GetSingleRef();
+                ScComplexRefData aRef;
+                aRef.Ref1 = rRef;
+                aRef.Ref2 = rRef;
+                rCxt.mpRefConv->makeRefStr(rBuf, rPos, rCxt.meGram, rCxt.maErrRef, rCxt.maTabNames, aRef, true);
+            }
+            else
+                rBuf.append(rCxt.maErrRef);
+        }
+        break;
+        case svDoubleRef:
+        {
+            if (rCxt.mpRefConv)
+            {
+                const ScComplexRefData& rRef = static_cast<const ScToken&>(rToken).GetDoubleRef();
+                rCxt.mpRefConv->makeRefStr(rBuf, rPos, rCxt.meGram, rCxt.maErrRef, rCxt.maTabNames, rRef, false);
+            }
+            else
+                rBuf.append(rCxt.maErrRef);
+        }
+        break;
+        case svMatrix:
+            // TODO : Implement this.
+        break;
+        case svIndex:
+            // TODO : Implement this.
+        break;
+        case svExternal:
+            // TODO : Implement this.
+        break;
+        case svError:
+        {
+            sal_uInt16 nErr = rToken.GetError();
+            OpCode eOpErr;
+            switch (nErr)
+            {
+                break;
+                case errDivisionByZero:
+                    eOpErr = ocErrDivZero;
+                break;
+                case errNoValue:
+                    eOpErr = ocErrValue;
+                break;
+                case errNoRef:
+                    eOpErr = ocErrRef;
+                break;
+                case errNoName:
+                    eOpErr = ocErrName;
+                break;
+                case errIllegalFPOperation:
+                    eOpErr = ocErrNum;
+                break;
+                case NOTAVAILABLE:
+                    eOpErr = ocErrNA;
+                break;
+                case errNoCode:
+                default:
+                    eOpErr = ocErrNull;
+            }
+            rBuf.append(rCxt.mxOpCodeMap->getSymbol(eOpErr));
+        }
+        break;
+        case svByte:
+        case svJump:
+        case svFAP:
+        case svMissing:
+        case svSep:
+        default:
+            ;
+    }
+}
+
+}
+
+OUString ScTokenArray::CreateString( sc::TokenStringContext& rCxt, const ScAddress& rPos ) const
+{
+    if (!nLen)
+        return OUString();
+
+    OUStringBuffer aBuf;
+
+    FormulaToken** p = pCode;
+    FormulaToken** pEnd = p + static_cast<size_t>(nLen);
+    for (; p != pEnd; ++p)
+    {
+        const FormulaToken* pToken = *p;
+        OpCode eOp = pToken->GetOpCode();
+        switch (eOp)
+        {
+            case ocPush:
+                appendTokenByType(rCxt, aBuf, *pToken, rPos);
+            break;
+            case ocSpaces:
+                // TODO : Handle intersection operator '!!'.
+                aBuf.append(sal_Unicode(' '));
+            break;
+            default:
+            {
+                if (eOp < rCxt.mxOpCodeMap->getSymbolCount())
+                    aBuf.append(rCxt.mxOpCodeMap->getSymbol(eOp));
+                else
+                    return OUString();
+            }
+        }
+    }
+
+    return aBuf.makeStringAndClear();
+}
+
 #if DEBUG_FORMULA_COMPILER
 void ScTokenArray::Dump() const
 {
diff --git a/sc/source/core/tool/tokenstringcontext.cxx b/sc/source/core/tool/tokenstringcontext.cxx
new file mode 100644
index 0000000..5fea0a9
--- /dev/null
+++ b/sc/source/core/tool/tokenstringcontext.cxx
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "tokenstringcontext.hxx"
+#include "compiler.hxx"
+
+using namespace com::sun::star;
+
+namespace sc {
+
+TokenStringContext::TokenStringContext( formula::FormulaGrammar::Grammar eGram ) :
+    meGram(eGram),
+    mpRefConv(ScCompiler::GetRefConvention(formula::FormulaGrammar::extractRefConvention(eGram)))
+{
+    ScCompiler aComp(NULL, ScAddress());
+    mxOpCodeMap = aComp.GetOpCodeMap(formula::FormulaGrammar::extractFormulaLanguage(eGram));
+    if (mxOpCodeMap)
+        maErrRef = mxOpCodeMap->getSymbol(ocErrRef);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 8819e6909568ec8e3feebb4226ef4f381af209a9
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Nov 14 14:57:21 2013 -0500

    Remove unused member.
    
    Change-Id: I8331251f77fb202375370a425e01862aa0f6310d

diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index f65d0b3..480d557 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -529,7 +529,6 @@ DBG_NAME(FormulaCompiler)
 FormulaCompiler::FormulaCompiler( FormulaTokenArray& rArr )
         :
         pArr( &rArr ),
-        pExternalRef(NULL),
         pStack( NULL ),
         nRecursion(0),
         nNumFmt( NUMBERFORMAT_UNDEFINED ),
@@ -546,7 +545,6 @@ FormulaCompiler::FormulaCompiler( FormulaTokenArray& rArr )
 FormulaCompiler::FormulaCompiler()
         :
         pArr( NULL ),
-        pExternalRef(NULL),
         pStack( NULL ),
         nRecursion(0),
         nNumFmt( NUMBERFORMAT_UNDEFINED ),
diff --git a/include/formula/FormulaCompiler.hxx b/include/formula/FormulaCompiler.hxx
index e851fcf..b450ed6 100644
--- a/include/formula/FormulaCompiler.hxx
+++ b/include/formula/FormulaCompiler.hxx
@@ -320,7 +320,6 @@ protected:
     FormulaTokenRef     mpToken;                // current token
     FormulaTokenRef     pCurrentFactorToken;    // current factor token (of Factor() method)
     FormulaTokenArray*  pArr;
-    ExternalReferenceHelper* pExternalRef;
 
     FormulaToken**      pCode;
     FormulaArrayStack*  pStack;
commit d9a914fe5b221f879c6fb7873c7e7011dc655421
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Nov 14 14:39:56 2013 -0500

    Identify methods that don't modify internal state and mark them const.
    
    Change-Id: Ie63d93d51640bfb80dc02bb226d742c2f9be96d8

diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index c42ee06..f65d0b3 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -963,7 +963,7 @@ sal_uInt16 FormulaCompiler::GetErrorConstant( const OUString& rName ) const
 }
 
 
-void FormulaCompiler::AppendErrorConstant( OUStringBuffer& rBuffer, sal_uInt16 nError )
+void FormulaCompiler::AppendErrorConstant( OUStringBuffer& rBuffer, sal_uInt16 nError ) const
 {
     OpCode eOp;
     switch (nError)
@@ -1875,7 +1875,7 @@ FormulaToken* FormulaCompiler::CreateStringFromToken( OUStringBuffer& rBuffer, F
 }
 
 
-void FormulaCompiler::AppendDouble( OUStringBuffer& rBuffer, double fVal )
+void FormulaCompiler::AppendDouble( OUStringBuffer& rBuffer, double fVal ) const
 {
     if ( mxSymbols->isEnglish() )
     {
@@ -1894,12 +1894,12 @@ void FormulaCompiler::AppendDouble( OUStringBuffer& rBuffer, double fVal )
     }
 }
 
-void FormulaCompiler::AppendBoolean( OUStringBuffer& rBuffer, bool bVal )
+void FormulaCompiler::AppendBoolean( OUStringBuffer& rBuffer, bool bVal ) const
 {
     rBuffer.append( mxSymbols->getSymbol( static_cast<OpCode>(bVal ? ocTrue : ocFalse)) );
 }
 
-void FormulaCompiler::AppendString( OUStringBuffer& rBuffer, const OUString & rStr )
+void FormulaCompiler::AppendString( OUStringBuffer& rBuffer, const OUString & rStr ) const
 {
     rBuffer.append( '"');
     if ( lcl_UnicodeStrChr( rStr.getStr(), '"' ) == NULL )
@@ -2074,27 +2074,27 @@ bool FormulaCompiler::HandleDbData()
     return true;
 }
 
-void FormulaCompiler::CreateStringFromSingleRef( OUStringBuffer& /*rBuffer*/, FormulaToken* /*pTokenP*/)
+void FormulaCompiler::CreateStringFromSingleRef( OUStringBuffer& /*rBuffer*/, FormulaToken* /*pTokenP*/) const
 {
 }
 
-void FormulaCompiler::CreateStringFromDoubleRef( OUStringBuffer& /*rBuffer*/, FormulaToken* /*pTokenP*/)
+void FormulaCompiler::CreateStringFromDoubleRef( OUStringBuffer& /*rBuffer*/, FormulaToken* /*pTokenP*/) const
 {
 }
 
-void FormulaCompiler::CreateStringFromIndex( OUStringBuffer& /*rBuffer*/, FormulaToken* /*pTokenP*/)
+void FormulaCompiler::CreateStringFromIndex( OUStringBuffer& /*rBuffer*/, FormulaToken* /*pTokenP*/) const
 {
 }
 
-void FormulaCompiler::CreateStringFromMatrix( OUStringBuffer& /*rBuffer*/, FormulaToken* /*pTokenP*/)
+void FormulaCompiler::CreateStringFromMatrix( OUStringBuffer& /*rBuffer*/, FormulaToken* /*pTokenP*/) const
 {
 }
 
-void FormulaCompiler::CreateStringFromExternal( OUStringBuffer& /*rBuffer*/, FormulaToken* /*pTokenP*/)
+void FormulaCompiler::CreateStringFromExternal( OUStringBuffer& /*rBuffer*/, FormulaToken* /*pTokenP*/) const
 {
 }
 
-void FormulaCompiler::LocalizeString( OUString& /*rName*/ )
+void FormulaCompiler::LocalizeString( OUString& /*rName*/ ) const
 {
 }
 
diff --git a/include/formula/FormulaCompiler.hxx b/include/formula/FormulaCompiler.hxx
index ff2ebf3..e851fcf 100644
--- a/include/formula/FormulaCompiler.hxx
+++ b/include/formula/FormulaCompiler.hxx
@@ -245,9 +245,9 @@ public:
     FormulaToken* CreateStringFromToken( OUStringBuffer& rBuffer, FormulaToken* pToken,
                                     bool bAllowArrAdvance = false );
 
-    void AppendBoolean( OUStringBuffer& rBuffer, bool bVal );
-    void AppendDouble( OUStringBuffer& rBuffer, double fVal );
-    void AppendString( OUStringBuffer& rBuffer, const OUString & rStr );
+    void AppendBoolean( OUStringBuffer& rBuffer, bool bVal ) const;
+    void AppendDouble( OUStringBuffer& rBuffer, double fVal ) const;
+    void AppendString( OUStringBuffer& rBuffer, const OUString & rStr ) const;
 
     /** Set symbol map corresponding to one of predefined formula::FormulaGrammar::Grammar,
         including an address reference convention. */
@@ -282,14 +282,14 @@ protected:
     virtual bool HandleSingleRef();
     virtual bool HandleDbData();
 
-    virtual void CreateStringFromExternal(OUStringBuffer& rBuffer, FormulaToken* pTokenP);
-    virtual void CreateStringFromSingleRef(OUStringBuffer& rBuffer,FormulaToken* pTokenP);
-    virtual void CreateStringFromDoubleRef(OUStringBuffer& rBuffer,FormulaToken* pTokenP);
-    virtual void CreateStringFromMatrix(OUStringBuffer& rBuffer,FormulaToken* pTokenP);
-    virtual void CreateStringFromIndex(OUStringBuffer& rBuffer,FormulaToken* pTokenP);
-    virtual void LocalizeString(OUString& rName );   // modify rName - input: exact name
+    virtual void CreateStringFromExternal(OUStringBuffer& rBuffer, FormulaToken* pTokenP) const;
+    virtual void CreateStringFromSingleRef(OUStringBuffer& rBuffer,FormulaToken* pTokenP) const;
+    virtual void CreateStringFromDoubleRef(OUStringBuffer& rBuffer,FormulaToken* pTokenP) const;
+    virtual void CreateStringFromMatrix(OUStringBuffer& rBuffer,FormulaToken* pTokenP) const;
+    virtual void CreateStringFromIndex(OUStringBuffer& rBuffer,FormulaToken* pTokenP) const;
+    virtual void LocalizeString( OUString& rName ) const;   // modify rName - input: exact name
 
-    void AppendErrorConstant( OUStringBuffer& rBuffer, sal_uInt16 nError );
+    void AppendErrorConstant( OUStringBuffer& rBuffer, sal_uInt16 nError ) const;
 
     bool   GetToken();
     OpCode NextToken();
diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx
index 3b366c0..4cd31a3 100644
--- a/sc/inc/compiler.hxx
+++ b/sc/inc/compiler.hxx
@@ -472,12 +472,12 @@ private:
     virtual bool HandleDbData();
 
     virtual formula::FormulaTokenRef ExtendRangeReference( formula::FormulaToken & rTok1, formula::FormulaToken & rTok2, bool bReuseDoubleRef );
-    virtual void CreateStringFromExternal(OUStringBuffer& rBuffer, formula::FormulaToken* pTokenP);
-    virtual void CreateStringFromSingleRef(OUStringBuffer& rBuffer,formula::FormulaToken* _pTokenP);
-    virtual void CreateStringFromDoubleRef(OUStringBuffer& rBuffer,formula::FormulaToken* _pTokenP);
-    virtual void CreateStringFromMatrix( OUStringBuffer& rBuffer, formula::FormulaToken* _pTokenP);
-    virtual void CreateStringFromIndex(OUStringBuffer& rBuffer,formula::FormulaToken* _pTokenP);
-    virtual void LocalizeString( OUString& rName );   // modify rName - input: exact name
+    virtual void CreateStringFromExternal(OUStringBuffer& rBuffer, formula::FormulaToken* pTokenP) const;
+    virtual void CreateStringFromSingleRef(OUStringBuffer& rBuffer,formula::FormulaToken* _pTokenP) const;
+    virtual void CreateStringFromDoubleRef(OUStringBuffer& rBuffer,formula::FormulaToken* _pTokenP) const;
+    virtual void CreateStringFromMatrix( OUStringBuffer& rBuffer, formula::FormulaToken* _pTokenP) const;
+    virtual void CreateStringFromIndex(OUStringBuffer& rBuffer,formula::FormulaToken* _pTokenP) const;
+    virtual void LocalizeString( OUString& rName ) const;   // modify rName - input: exact name
 
     /// Access the CharTable flags
     inline sal_uLong GetCharTableFlags( sal_Unicode c, sal_Unicode cLast )
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index b297f66..6641451 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -4122,7 +4122,7 @@ bool ScCompiler::IsCharFlagAllConventions(
         return false;
 }
 
-void ScCompiler::CreateStringFromExternal(OUStringBuffer& rBuffer, FormulaToken* pTokenP)
+void ScCompiler::CreateStringFromExternal(OUStringBuffer& rBuffer, FormulaToken* pTokenP) const
 {
     FormulaToken* t = pTokenP;
     ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
@@ -4150,8 +4150,8 @@ void ScCompiler::CreateStringFromExternal(OUStringBuffer& rBuffer, FormulaToken*
     }
 }
 
-void ScCompiler::CreateStringFromMatrix( OUStringBuffer& rBuffer,
-                                           FormulaToken* pTokenP)
+void ScCompiler::CreateStringFromMatrix(
+    OUStringBuffer& rBuffer, FormulaToken* pTokenP) const
 {
     const ScMatrix* pMatrix = static_cast<ScToken*>(pTokenP)->GetMatrix();
     SCSIZE nC, nMaxC, nR, nMaxR;
@@ -4195,10 +4195,10 @@ void ScCompiler::CreateStringFromMatrix( OUStringBuffer& rBuffer,
     rBuffer.append( mxSymbols->getSymbol(ocArrayClose) );
 }
 
-void ScCompiler::CreateStringFromSingleRef(OUStringBuffer& rBuffer,FormulaToken* _pTokenP)
+void ScCompiler::CreateStringFromSingleRef(OUStringBuffer& rBuffer,FormulaToken* _pTokenP) const
 {
     const OpCode eOp = _pTokenP->GetOpCode();
-    ScSingleRefData& rRef = static_cast<ScToken*>(_pTokenP)->GetSingleRef();
+    const ScSingleRefData& rRef = static_cast<const ScToken*>(_pTokenP)->GetSingleRef();
     ScComplexRefData aRef;
     aRef.Ref1 = aRef.Ref2 = rRef;
     if ( eOp == ocColRowName )
@@ -4220,12 +4220,12 @@ void ScCompiler::CreateStringFromSingleRef(OUStringBuffer& rBuffer,FormulaToken*
         pConv->MakeRefStr( rBuffer, *this, aRef, true );
 }
 
-void ScCompiler::CreateStringFromDoubleRef(OUStringBuffer& rBuffer,FormulaToken* _pTokenP)
+void ScCompiler::CreateStringFromDoubleRef(OUStringBuffer& rBuffer,FormulaToken* _pTokenP) const
 {
     pConv->MakeRefStr( rBuffer, *this, static_cast<ScToken*>(_pTokenP)->GetDoubleRef(), false );
 }
 
-void ScCompiler::CreateStringFromIndex(OUStringBuffer& rBuffer,FormulaToken* _pTokenP)
+void ScCompiler::CreateStringFromIndex(OUStringBuffer& rBuffer,FormulaToken* _pTokenP) const
 {
     const OpCode eOp = _pTokenP->GetOpCode();
     OUStringBuffer aBuffer;
@@ -4233,14 +4233,14 @@ void ScCompiler::CreateStringFromIndex(OUStringBuffer& rBuffer,FormulaToken* _pT
     {
         case ocName:
         {
-            ScRangeData* pData = GetRangeData( *_pTokenP);
+            const ScRangeData* pData = GetRangeData( *_pTokenP);
             if (pData)
                 aBuffer.append(pData->GetName());
         }
         break;
         case ocDBArea:
         {
-            ScDBData* pDBData = pDoc->GetDBCollection()->getNamedDBs().findByIndex(_pTokenP->GetIndex());
+            const ScDBData* pDBData = pDoc->GetDBCollection()->getNamedDBs().findByIndex(_pTokenP->GetIndex());
             if (pDBData)
                 aBuffer.append(pDBData->GetName());
         }
@@ -4254,7 +4254,7 @@ void ScCompiler::CreateStringFromIndex(OUStringBuffer& rBuffer,FormulaToken* _pT
         rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
 }
 
-void ScCompiler::LocalizeString( OUString& rName )
+void ScCompiler::LocalizeString( OUString& rName ) const
 {
     ScGlobal::GetAddInCollection()->LocalizeString( rName );
 }
commit 6a4b377c1a5794efee4cbdc93289bc9ce5ead730
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Nov 14 12:14:12 2013 -0500

    Do everything on main thread when the thread count is 1.
    
    This helps debugging / profiling easier.
    
    Change-Id: I7834585bf2aa5d5f550bd218b9845ec964b06655

diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx
index 343c545..7472d3d 100644
--- a/sc/source/filter/oox/formulabuffer.cxx
+++ b/sc/source/filter/oox/formulabuffer.cxx
@@ -269,6 +269,25 @@ void applyCellFormulaValues(
     }
 }
 
+void processSheetFormulaCells(
+    ScDocumentImport& rDoc, FormulaBuffer::SheetItem& rItem, SvNumberFormatter& rFormatter )
+{
+    if (rItem.mpSharedFormulaEntries && rItem.mpSharedFormulaIDs)
+        applySharedFormulas(rDoc, rFormatter, *rItem.mpSharedFormulaEntries, *rItem.mpSharedFormulaIDs);
+
+    if (rItem.mpCellFormulas)
+    {
+        CachedTokenArray aCache(rDoc.getDoc());
+        applyCellFormulas(rDoc, aCache, rFormatter, *rItem.mpCellFormulas);
+    }
+
+    if (rItem.mpArrayFormulas)
+        applyArrayFormulas(rDoc, rFormatter, *rItem.mpArrayFormulas);
+
+    if (rItem.mpCellFormulaValues)
+        applyCellFormulaValues(rDoc, *rItem.mpCellFormulaValues);
+}
+
 class WorkerThread : public salhelper::Thread
 {
     ScDocumentImport& mrDoc;
@@ -288,20 +307,7 @@ public:
 protected:
     virtual void execute()
     {
-        if (mrItem.mpSharedFormulaEntries && mrItem.mpSharedFormulaIDs)
-            applySharedFormulas(mrDoc, *mpFormatter, *mrItem.mpSharedFormulaEntries, *mrItem.mpSharedFormulaIDs);
-
-        if (mrItem.mpCellFormulas)
-        {
-            CachedTokenArray aCache(mrDoc.getDoc());
-            applyCellFormulas(mrDoc, aCache, *mpFormatter, *mrItem.mpCellFormulas);
-        }
-
-        if (mrItem.mpArrayFormulas)
-            applyArrayFormulas(mrDoc, *mpFormatter, *mrItem.mpArrayFormulas);
-
-        if (mrItem.mpCellFormulaValues)
-            applyCellFormulaValues(mrDoc, *mrItem.mpCellFormulaValues);
+        processSheetFormulaCells(mrDoc, mrItem, *mpFormatter);
     }
 };
 
@@ -345,36 +351,43 @@ void FormulaBuffer::finalizeImport()
     for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
         aSheetItems.push_back(getSheetItem(nTab));
 
-    typedef rtl::Reference<WorkerThread> WorkerThreadRef;
-    std::vector<WorkerThreadRef> aThreads;
-    aThreads.reserve(nThreadCount);
-
     std::vector<SheetItem>::iterator it = aSheetItems.begin(), itEnd = aSheetItems.end();
 
-    // TODO: Right now we are spawning multiple threads all at once and block
-    // on them all at once.  Any more clever thread management would require
-    // use of condition variables which our own osl thread framework seems to
-    // lack.
-    while (it != itEnd)
+    if (nThreadCount == 1)
+    {
+        for (; it != itEnd; ++it)
+            processSheetFormulaCells(rDoc, *it, *rDoc.getDoc().GetFormatTable());
+    }
+    else
     {
-        for (size_t i = 0; i < nThreadCount; ++i)
+        typedef rtl::Reference<WorkerThread> WorkerThreadRef;
+        std::vector<WorkerThreadRef> aThreads;
+        aThreads.reserve(nThreadCount);
+        // TODO: Right now we are spawning multiple threads all at once and block
+        // on them all at once.  Any more clever thread management would require
+        // use of condition variables which our own osl thread framework seems to
+        // lack.
+        while (it != itEnd)
         {
-            if (it == itEnd)
-                break;
+            for (size_t i = 0; i < nThreadCount; ++i)
+            {
+                if (it == itEnd)
+                    break;
 
-            WorkerThreadRef xThread(new WorkerThread(rDoc, *it, rDoc.getDoc().CreateFormatTable()));
-            ++it;
-            aThreads.push_back(xThread);
-            xThread->launch();
-        }
+                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();
-        }
+            for (size_t i = 0, n = aThreads.size(); i < n; ++i)
+            {
+                if (aThreads[i].is())
+                    aThreads[i]->join();
+            }
 
-        aThreads.clear();
+            aThreads.clear();
+        }
     }
 
     rDoc.getDoc().SetAutoNameCache(NULL);
commit ae79b40f725ac28f8940bc9d97fd137088c20a22
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Nov 14 09:49:15 2013 -0500

    Optimize SvtBroadcaster for insertion.
    
    This helps file load performance at the slight overhead during editing.
    That said, the overhead during editing is only in theory (not measured) and
    shouldn't be that much even in theory.
    
    Change-Id: If22ea34acb0cda311575ac3ed8ce1a8eb69ae33a

diff --git a/include/svl/broadcast.hxx b/include/svl/broadcast.hxx
index 80d9568..6a6bc03 100644
--- a/include/svl/broadcast.hxx
+++ b/include/svl/broadcast.hxx
@@ -21,7 +21,7 @@
 
 #include <svl/svldllapi.h>
 
-#include <boost/unordered_set.hpp>
+#include <vector>
 
 class SvtListener;
 class SfxHint;
@@ -31,11 +31,18 @@ class SVL_DLLPUBLIC SvtBroadcaster
 public:
     friend class SvtListener;
 
-    typedef boost::unordered_set<SvtListener*> ListenersType;
+    typedef std::vector<SvtListener*> ListenersType;
 
 private:
     const SvtBroadcaster&   operator=(const SvtBroadcaster &); // verboten
 
+    /**
+     * Ensure that the container doesn't contain any duplicated listener
+     * entries. As a side effect, the listeners get sorted by pointer values
+     * after this call.
+     */
+    void Normalize();
+
     void Add( SvtListener* p );
     void Remove( SvtListener* p );
 
@@ -55,7 +62,8 @@ public:
 
 private:
     ListenersType maListeners;
-    bool mbDying;
+    bool mbDisposing:1;
+    bool mbNormalized:1;
 };
 
 
diff --git a/svl/source/notify/broadcast.cxx b/svl/source/notify/broadcast.cxx
index 7e59e36..96d34a7 100644
--- a/svl/source/notify/broadcast.cxx
+++ b/svl/source/notify/broadcast.cxx
@@ -62,32 +62,49 @@ public:
 
 }
 
+void SvtBroadcaster::Normalize()
+{
+    if (mbNormalized)
+        return;
+
+    std::sort(maListeners.begin(), maListeners.end());
+    ListenersType::iterator itUniqueEnd = std::unique(maListeners.begin(), maListeners.end());
+    maListeners.erase(itUniqueEnd, maListeners.end());
+    mbNormalized = true;
+}
+
 void SvtBroadcaster::Add( SvtListener* p )
 {
-    maListeners.insert(p);
+    maListeners.push_back(p);
+    mbNormalized = false;
 }
 
 void SvtBroadcaster::Remove( SvtListener* p )
 {
-    if (mbDying)
+    if (mbDisposing)
         return;
 
-    maListeners.erase(p);
+    Normalize();
+    std::pair<ListenersType::iterator,ListenersType::iterator> r =
+        std::equal_range(maListeners.begin(), maListeners.end(), p);
+
+    if (r.first != r.second)
+        maListeners.erase(r.first, r.second);
     if (maListeners.empty())
         ListenersGone();
 }
 
-SvtBroadcaster::SvtBroadcaster() : mbDying(false) {}
+SvtBroadcaster::SvtBroadcaster() : mbDisposing(false), mbNormalized(false) {}
 
 SvtBroadcaster::SvtBroadcaster( const SvtBroadcaster &rBC ) :
-    maListeners(rBC.maListeners), mbDying(false)
+    maListeners(rBC.maListeners), mbDisposing(false), mbNormalized(rBC.mbNormalized)
 {
     std::for_each(maListeners.begin(), maListeners.end(), StartListeningHandler(*this));
 }
 
 SvtBroadcaster::~SvtBroadcaster()
 {
-    mbDying = true;
+    mbDisposing = true;
     Broadcast( SfxSimpleHint(SFX_HINT_DYING) );
 
     // unregister all listeners.
@@ -96,6 +113,7 @@ SvtBroadcaster::~SvtBroadcaster()
 
 void SvtBroadcaster::Broadcast( const SfxHint &rHint )
 {
+    Normalize();
     std::for_each(maListeners.begin(), maListeners.end(), NotifyHandler(*this, rHint));
 }
 
commit f076c62d5cce5425d903b861827c83c16a040b86
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Nov 13 22:04:49 2013 -0500

    No need to individually remove listeners when being destroyed.
    
    Otherwise a crash would ensue.
    
    Change-Id: I9a52524cc205765d059745e9f7e914b636667cb6

diff --git a/include/svl/broadcast.hxx b/include/svl/broadcast.hxx
index ab62d48..80d9568 100644
--- a/include/svl/broadcast.hxx
+++ b/include/svl/broadcast.hxx
@@ -55,6 +55,7 @@ public:
 
 private:
     ListenersType maListeners;
+    bool mbDying;
 };
 
 
diff --git a/svl/source/notify/broadcast.cxx b/svl/source/notify/broadcast.cxx
index 79c1757..7e59e36 100644
--- a/svl/source/notify/broadcast.cxx
+++ b/svl/source/notify/broadcast.cxx
@@ -69,21 +69,25 @@ void SvtBroadcaster::Add( SvtListener* p )
 
 void SvtBroadcaster::Remove( SvtListener* p )
 {
+    if (mbDying)
+        return;
+
     maListeners.erase(p);
     if (maListeners.empty())
         ListenersGone();
 }
 
-SvtBroadcaster::SvtBroadcaster() {}
+SvtBroadcaster::SvtBroadcaster() : mbDying(false) {}
 
 SvtBroadcaster::SvtBroadcaster( const SvtBroadcaster &rBC ) :
-    maListeners(rBC.maListeners)
+    maListeners(rBC.maListeners), mbDying(false)
 {
     std::for_each(maListeners.begin(), maListeners.end(), StartListeningHandler(*this));
 }
 
 SvtBroadcaster::~SvtBroadcaster()
 {
+    mbDying = true;
     Broadcast( SfxSimpleHint(SFX_HINT_DYING) );
 
     // unregister all listeners.
commit 18d07b2affbbbfb2ff9152d3ad8d1744fe75ab47
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Wed Nov 13 20:33:50 2013 -0500

    Rework SvtListener and SvtBroadcaster internals.
    
    The old code was simply awkward.
    
    Change-Id: I1a58a9af86c100be238d306570b40f70c5100314

diff --git a/include/svl/broadcast.hxx b/include/svl/broadcast.hxx
index 0b533ba..ab62d48 100644
--- a/include/svl/broadcast.hxx
+++ b/include/svl/broadcast.hxx
@@ -20,36 +20,41 @@
 #define INCLUDED_SVL_BROADCAST_HXX
 
 #include <svl/svldllapi.h>
-#include <tools/rtti.hxx>
+
+#include <boost/unordered_set.hpp>
 
 class SvtListener;
 class SfxHint;
-class SvtListenerBase;
-
-//-------------------------------------------------------------------------
 
 class SVL_DLLPUBLIC SvtBroadcaster
 {
-friend class SvtListener;
-friend class SvtListenerBase;
-friend class SvtListenerIter;
-    SvtListenerBase* pRoot;
+public:
+    friend class SvtListener;
+
+    typedef boost::unordered_set<SvtListener*> ListenersType;
 
+private:
     const SvtBroadcaster&   operator=(const SvtBroadcaster &); // verboten
 
+    void Add( SvtListener* p );
+    void Remove( SvtListener* p );
+
 protected:
     virtual void            ListenersGone();
 
 public:
-                            TYPEINFO();
-
                             SvtBroadcaster();
                             SvtBroadcaster( const SvtBroadcaster &rBC );
     virtual                 ~SvtBroadcaster();
 
     void                    Broadcast( const SfxHint &rHint );
 
-    sal_Bool                    HasListeners() const { return 0 != pRoot; }
+    ListenersType& GetAllListeners();
+
+    bool HasListeners() const;
+
+private:
+    ListenersType maListeners;
 };
 
 
diff --git a/include/svl/listener.hxx b/include/svl/listener.hxx
index 4204b2b..c871023 100644
--- a/include/svl/listener.hxx
+++ b/include/svl/listener.hxx
@@ -20,34 +20,30 @@
 #define INCLUDED_SVL_LISTENER_HXX
 
 #include <svl/svldllapi.h>
-#include <tools/rtti.hxx>
+
+#include <boost/unordered_set.hpp>
 
 class SvtBroadcaster;
 class SfxHint;
-class SvtListenerBase;
-
-//-------------------------------------------------------------------------
 
 class SVL_DLLPUBLIC SvtListener
 {
-    friend class SvtListenerBase;
-    SvtListenerBase *pBrdCastLst;
+    typedef boost::unordered_set<SvtBroadcaster*> BroadcastersType;
+    BroadcastersType maBroadcasters;
 
     const SvtListener&  operator=(const SvtListener &); // n.i., ist verboten
 
 public:
-    TYPEINFO();
-
-                        SvtListener();
-                        SvtListener( const SvtListener &rCopy );
-    virtual             ~SvtListener();
+    SvtListener();
+    SvtListener( const SvtListener &r );
+    virtual ~SvtListener();
 
-    sal_Bool                StartListening( SvtBroadcaster& rBroadcaster );
-    sal_Bool                EndListening( SvtBroadcaster& rBroadcaster );
-    void                EndListeningAll();
-    sal_Bool                IsListening( SvtBroadcaster& rBroadcaster ) const;
+    bool StartListening( SvtBroadcaster& rBroadcaster );
+    bool EndListening( SvtBroadcaster& rBroadcaster );
+    void EndListeningAll();
+    bool IsListening( SvtBroadcaster& rBroadcaster ) const;
 
-    sal_Bool                HasBroadcaster() const { return 0 != pBrdCastLst; }
+    bool HasBroadcaster() const;
 
     virtual void        Notify( SvtBroadcaster& rBC, const SfxHint& rHint );
 };
diff --git a/include/svl/listeneriter.hxx b/include/svl/listeneriter.hxx
deleted file mode 100644
index 7d91fa3..0000000
--- a/include/svl/listeneriter.hxx
+++ /dev/null
@@ -1,65 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements. See the NOTICE file distributed
- *   with this work for additional information regarding copyright
- *   ownership. The ASF licenses this file to you under the Apache
- *   License, Version 2.0 (the "License"); you may not use this file
- *   except in compliance with the License. You may obtain a copy of
- *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-#ifndef INCLUDED_SVL_LISTENERITER_HXX
-#define INCLUDED_SVL_LISTENERITER_HXX
-
-#include <svl/svldllapi.h>
-#include <tools/rtti.hxx>
-
-class SvtListener;
-class SvtListenerBase;
-class SvtBroadcaster;
-
-//-------------------------------------------------------------------------
-
-class SVL_DLLPUBLIC SvtListenerIter
-{
-    friend class SvtListenerBase;
-
-    SvtBroadcaster& rRoot;
-    SvtListenerBase *pAkt, *pDelNext;
-
-    // for the update of all iterator's, if a listener is added or removed
-    // at the same time.
-    static SvtListenerIter *pListenerIters;
-    SvtListenerIter *pNxtIter;
-
-    SVL_DLLPRIVATE static void RemoveListener( SvtListenerBase& rDel,
-                                               SvtListenerBase* pNext );
-
-public:
-    SvtListenerIter( SvtBroadcaster& );
-    ~SvtListenerIter();
-
-    const SvtBroadcaster& GetBroadcaster() const    { return rRoot; }
-          SvtBroadcaster& GetBroadcaster()          { return rRoot; }
-
-    SvtListener* GoNext();          // to the next
-
-    SvtListener* GoStart();         // to the start of the list
-
-    SvtListener* GetCurr() const;   // returns the current
-
-    int IsChanged() const       { return pDelNext != pAkt; }
-};
-
-
-#endif
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/pch/precompiled_sc.hxx b/sc/inc/pch/precompiled_sc.hxx
index d57563c..a83fe72 100644
--- a/sc/inc/pch/precompiled_sc.hxx
+++ b/sc/inc/pch/precompiled_sc.hxx
@@ -711,7 +711,6 @@
 #include <svl/itemset.hxx>
 #include <svl/languageoptions.hxx>
 #include <svl/listener.hxx>
-#include <svl/listeneriter.hxx>
 #include <svl/macitem.hxx>
 #include <svl/numuno.hxx>
 #include <svl/poolcach.hxx>
diff --git a/sc/source/core/data/bcaslot.cxx b/sc/source/core/data/bcaslot.cxx
index b7ed7f5..4578fd9 100644
--- a/sc/source/core/data/bcaslot.cxx
+++ b/sc/source/core/data/bcaslot.cxx
@@ -19,7 +19,6 @@
 
 #include <sfx2/objsh.hxx>
 #include <svl/listener.hxx>
-#include <svl/listeneriter.hxx>
 
 #include "document.hxx"
 #include "brdcst.hxx"
@@ -419,11 +418,12 @@ void ScBroadcastAreaSlot::UpdateInsert( ScBroadcastArea* pArea )
         if (pArea != pTarget)
         {
             SvtBroadcaster& rTarget = pTarget->GetBroadcaster();
-            SvtListenerIter it( pArea->GetBroadcaster());
-            for (SvtListener* pListener = it.GetCurr(); pListener;
-                    pListener = it.GoNext())
+            SvtBroadcaster::ListenersType& rListeners = pArea->GetBroadcaster().GetAllListeners();
+            SvtBroadcaster::ListenersType::iterator it = rListeners.begin(), itEnd = rListeners.end();
+            for (; it != itEnd; ++it)
             {
-                pListener->StartListening( rTarget);
+                SvtListener& rListener = **it;
+                rListener.StartListening(rTarget);
             }
         }
     }
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index fbd0fbf..240677b 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -60,7 +60,6 @@
 #include <editeng/justifyitem.hxx>
 #include <svl/zforlist.hxx>
 #include <svl/broadcast.hxx>
-#include <svl/listeneriter.hxx>
 #include <vcl/outdev.hxx>
 #include "formula/errorcodes.hxx"
 #include "formula/vectortoken.hxx"
@@ -3075,11 +3074,13 @@ void ScColumn::MoveListeners( SvtBroadcaster& rSource, SCROW nDestRow )
         maBroadcasters.set(nDestRow, pBC);
     }
 
-    SvtListenerIter aIter(rSource);
-    for (SvtListener* pLst = aIter.GoStart(); pLst; pLst = aIter.GoNext())
+    SvtBroadcaster::ListenersType& rListeners = rSource.GetAllListeners();
+    SvtBroadcaster::ListenersType::iterator it = rListeners.begin(), itEnd = rListeners.end();
+    for (; it != itEnd; ++it)
     {
-        pLst->StartListening(*pBC);
-        pLst->EndListening(rSource);
+        SvtListener& rLst = **it;
+        rLst.StartListening(*pBC);
+        rLst.EndListening(rSource);
     }
 }
 
diff --git a/svl/Library_svl.mk b/svl/Library_svl.mk
index 283e06b..d6d83b5 100644
--- a/svl/Library_svl.mk
+++ b/svl/Library_svl.mk
@@ -119,8 +119,6 @@ $(eval $(call gb_Library_add_exception_objects,svl,\
     svl/source/notify/hint \
     svl/source/notify/isethint \
     svl/source/notify/listener \
-    svl/source/notify/listenerbase \
-    svl/source/notify/listeneriter \
     svl/source/notify/lstner \
     svl/source/notify/smplhint \
     svl/source/numbers/numfmuno \
diff --git a/svl/source/notify/broadcast.cxx b/svl/source/notify/broadcast.cxx
index 4cdaa14..79c1757 100644
--- a/svl/source/notify/broadcast.cxx
+++ b/svl/source/notify/broadcast.cxx
@@ -17,85 +17,94 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
-
-#include <svl/listener.hxx>
-#include <svl/listeneriter.hxx>
 #include <svl/broadcast.hxx>
+#include <svl/listener.hxx>
 #include <svl/smplhint.hxx>
 
+namespace {
 
-TYPEINIT0(SvtBroadcaster);
+class StartListeningHandler : std::unary_function<SvtListener*, void>
+{
+    SvtBroadcaster& mrBC;
+public:
+    StartListeningHandler( SvtBroadcaster& rBC ) : mrBC(rBC) {}
 
+    void operator() ( SvtListener* p )
+    {
+        p->StartListening(mrBC);
+    }
+};
 
-// simple ctor of class SvtBroadcaster
+class EndListeningHandler : std::unary_function<SvtListener*, void>
+{
+    SvtBroadcaster& mrBC;
+public:
+    EndListeningHandler( SvtBroadcaster& rBC ) : mrBC(rBC) {}
 
-SvtBroadcaster::SvtBroadcaster()
-    : pRoot( 0 )
+    void operator() ( SvtListener* p )
+    {
+        p->EndListening(mrBC);
+    }
+};
+
+class NotifyHandler : std::unary_function<SvtListener*, void>
 {
-}
+    SvtBroadcaster& mrBC;
+    const SfxHint& mrHint;
+public:
+    NotifyHandler( SvtBroadcaster& rBC, const SfxHint& rHint ) : mrBC(rBC), mrHint(rHint) {}
+
+    void operator() ( SvtListener* p )
+    {
+        p->Notify(mrBC, mrHint);
+    }
+};
 
+}
 
-// copy ctor of class SvtBroadcaster
+void SvtBroadcaster::Add( SvtListener* p )
+{
+    maListeners.insert(p);
+}
 
-SvtBroadcaster::SvtBroadcaster( const SvtBroadcaster &rBC )
-    : pRoot( 0 )
+void SvtBroadcaster::Remove( SvtListener* p )
 {
-    SvtListenerIter aIter( (SvtBroadcaster&)rBC );
-    SvtListener* pLast = aIter.GoStart();
-    if( pLast )
-        do {
-            pLast->StartListening( *this );
-        } while( 0 != ( pLast = aIter.GoNext() ));
+    maListeners.erase(p);
+    if (maListeners.empty())
+        ListenersGone();
 }
 
+SvtBroadcaster::SvtBroadcaster() {}
 
-// unregister all listeners
+SvtBroadcaster::SvtBroadcaster( const SvtBroadcaster &rBC ) :
+    maListeners(rBC.maListeners)
+{
+    std::for_each(maListeners.begin(), maListeners.end(), StartListeningHandler(*this));
+}
 
 SvtBroadcaster::~SvtBroadcaster()
 {
     Broadcast( SfxSimpleHint(SFX_HINT_DYING) );
 
-    SvtListenerIter aIter( *this );
-    SvtListener* pLast = aIter.GoStart();
-    if( pLast )
-        do {
-            pLast->EndListening( *this );
-            if( !HasListeners() )       // all gone ??
-                break;
-        } while( 0 != ( pLast = aIter.GoNext() ));
+    // unregister all listeners.
+    std::for_each(maListeners.begin(), maListeners.end(), EndListeningHandler(*this));
 }
 
-
-// broadcast immedeately
-
 void SvtBroadcaster::Broadcast( const SfxHint &rHint )
 {
-    // is anybody to notify?
-    if( HasListeners() /* && !IsModifyLocked()*/ )
-    {
-//      LockModify();
-//      bInModify = sal_True;
-
-        SvtListenerIter aIter( *this );
-        SvtListener* pLast = aIter.GoStart();
-        if( pLast )
-            do {
-                pLast->Notify( *this, rHint );
-                if( !HasListeners() )       // all gone ??
-                    break;
-            } while( 0 != ( pLast = aIter.GoNext() ));
-
-//      bInModify = sal_False;
-//      UnlockModify();
-    }
+    std::for_each(maListeners.begin(), maListeners.end(), NotifyHandler(*this, rHint));
 }
 
+void SvtBroadcaster::ListenersGone() {}
 
+SvtBroadcaster::ListenersType& SvtBroadcaster::GetAllListeners()
+{
+    return maListeners;
+}
 
-// called, if no more listeners exists
-
-void SvtBroadcaster::ListenersGone()
+bool SvtBroadcaster::HasListeners() const
 {
+    return !maListeners.empty();
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/notify/listener.cxx b/svl/source/notify/listener.cxx
index fd8616d..59d3ef9 100644
--- a/svl/source/notify/listener.cxx
+++ b/svl/source/notify/listener.cxx
@@ -17,117 +17,68 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
-
-#include <tools/debug.hxx>
-#include <svl/broadcast.hxx>
 #include <svl/listener.hxx>
-#include "listenerbase.hxx"
-#include <svl/listeneriter.hxx>
-
-
-TYPEINIT0(SvtListener);
-
-// simple ctor of class SvtListener
-
-SvtListener::SvtListener()
-    : pBrdCastLst( 0 )
-{
-}
-
-// copy ctor of class SvtListener
+#include <svl/broadcast.hxx>
+#include <tools/debug.hxx>
 
-SvtListener::SvtListener( const SvtListener &rListener )
-    : pBrdCastLst( 0 )
-{
-    SvtListenerBase* pLst = rListener.pBrdCastLst;
-    while( pLst )
-    {
-        new SvtListenerBase( *this, *pLst->GetBroadcaster() );
-        pLst = pLst->GetNext();
-    }
-}
+SvtListener::SvtListener() {}
 
-// unregisteres the SvtListener from its SvtBroadcasters
+SvtListener::SvtListener( const SvtListener &r ) :
+    maBroadcasters(r.maBroadcasters) {}
 
 SvtListener::~SvtListener()
 {
+    // Unregister itself from all broadcasters it's listening to.
     EndListeningAll();
 }
 
-
 // registeres at a specific SvtBroadcaster
 
-sal_Bool SvtListener::StartListening( SvtBroadcaster& rBroadcaster )
+bool SvtListener::StartListening( SvtBroadcaster& rBroadcaster )
 {
-    const SvtListenerBase* pLst = pBrdCastLst;
-    while( pLst )
+    std::pair<BroadcastersType::iterator, bool> r =
+        maBroadcasters.insert(&rBroadcaster);
+    if (r.second)
     {
-        if( &rBroadcaster == pLst->GetBroadcaster() )
-        {
-            // double, than return
-            return sal_False;
-        }
-        pLst = pLst->GetNext();
+        // This is a new broadcaster.
+        rBroadcaster.Add(this);
     }
-    new SvtListenerBase( *this, rBroadcaster );
-    return sal_True;
+    return r.second;
 }
 
-
-// unregisteres at a specific SvtBroadcaster
-
-sal_Bool SvtListener::EndListening( SvtBroadcaster& rBroadcaster )
+bool SvtListener::EndListening( SvtBroadcaster& rBroadcaster )
 {
-    SvtListenerBase *pLst = pBrdCastLst, *pPrev = pLst;
-    while( pLst )
-    {
-        if( &rBroadcaster == pLst->GetBroadcaster() )
-        {
-            if( pBrdCastLst == pLst )
-                pBrdCastLst = pLst->GetNext();
-            else
-                pPrev->SetNext( pLst->GetNext() );
-
-            delete pLst;
-            return sal_True;
-        }
-        pPrev = pLst;
-        pLst = pLst->GetNext();
-    }
-    return sal_False;
+    BroadcastersType::iterator it = maBroadcasters.find(&rBroadcaster);
+    if (it == maBroadcasters.end())
+        // Not listening to this broadcaster.
+        return false;
+
+    rBroadcaster.Remove(this);
+    maBroadcasters.erase(it);
+    return true;
 }
 
-
-// unregisteres all Broadcasters
-
 void SvtListener::EndListeningAll()
 {
-    SvtListenerBase *pLst = pBrdCastLst;
-    while( pLst )
+    BroadcastersType::iterator it = maBroadcasters.begin(), itEnd = maBroadcasters.end();
+    for (; it != itEnd; ++it)
     {
-        SvtListenerBase *pDel = pLst;
-        pLst = pLst->GetNext();
-
-        delete pDel;
+        SvtBroadcaster& rBC = **it;
+        rBC.Remove(this);
     }
-    pBrdCastLst = 0;
+    maBroadcasters.clear();
 }
 
 
-sal_Bool SvtListener::IsListening( SvtBroadcaster& rBroadcaster ) const
+bool SvtListener::IsListening( SvtBroadcaster& rBroadcaster ) const
 {
-    const SvtListenerBase *pLst = pBrdCastLst;
-    while( pLst )
-    {
-        if( &rBroadcaster == pLst->GetBroadcaster() )
-            break;
-        pLst = pLst->GetNext();
-    }
-    return 0 != pLst;
+    return maBroadcasters.count(&rBroadcaster) > 0;
 }
 
-
-// base implementation of notification handler
+bool SvtListener::HasBroadcaster() const
+{
+    return !maBroadcasters.empty();
+}
 
 void SvtListener::Notify( SvtBroadcaster&
 #ifdef DBG_UTIL
diff --git a/svl/source/notify/listenerbase.cxx b/svl/source/notify/listenerbase.cxx
deleted file mode 100644
index 73b5f34..0000000
--- a/svl/source/notify/listenerbase.cxx
+++ /dev/null
@@ -1,66 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements. See the NOTICE file distributed
- *   with this work for additional information regarding copyright
- *   ownership. The ASF licenses this file to you under the Apache
- *   License, Version 2.0 (the "License"); you may not use this file
- *   except in compliance with the License. You may obtain a copy of
- *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-
-#include "listenerbase.hxx"
-#include <svl/listeneriter.hxx>
-#include <svl/listener.hxx>
-#include <svl/broadcast.hxx>
-
-
-SvtListenerBase::SvtListenerBase( SvtListener& rLst,
-                                  SvtBroadcaster& rBroadcaster )
-    : pLeft( 0 ), pRight( 0 ),
-    pBroadcaster( &rBroadcaster ), pListener( &rLst )
-{
-    pNext = rLst.pBrdCastLst;
-    rLst.pBrdCastLst = this;
-
-    if( pBroadcaster->pRoot )
-    {
-        // set ever behind the root
-        pRight = pBroadcaster->pRoot->pRight;
-        pBroadcaster->pRoot->pRight = this;
-        this->pLeft = pBroadcaster->pRoot;
-        if( pRight )
-            pRight->pLeft = this;
-    }
-    else
-        pBroadcaster->pRoot = this;
-}
-
-SvtListenerBase::~SvtListenerBase()
-{
-    SvtListenerBase *pR = pRight, *pL = pLeft;
-    if( pBroadcaster->pRoot )
-        pBroadcaster->pRoot = pL ? pL : pR;
-
-    if( pL )
-        pL->pRight = pR;
-    if( pR )
-        pR->pLeft = pL;
-
-    SvtListenerIter::RemoveListener( *this, pR );
-
-    if( !pBroadcaster->pRoot )
-        pBroadcaster->ListenersGone();
-}
-
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/notify/listenerbase.hxx b/svl/source/notify/listenerbase.hxx
deleted file mode 100644
index 9473953..0000000
--- a/svl/source/notify/listenerbase.hxx
+++ /dev/null
@@ -1,50 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements. See the NOTICE file distributed
- *   with this work for additional information regarding copyright
- *   ownership. The ASF licenses this file to you under the Apache
- *   License, Version 2.0 (the "License"); you may not use this file
- *   except in compliance with the License. You may obtain a copy of
- *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-#ifndef INCLUDED_SVL_SOURCE_NOTIFY_LISTENERBASE_HXX
-#define INCLUDED_SVL_SOURCE_NOTIFY_LISTENERBASE_HXX
-
-class SvtBroadcaster;
-class SvtListener;
-
-class SvtListenerBase
-{
-    SvtListenerBase *pNext;
-    SvtListenerBase *pLeft, *pRight;
-    SvtBroadcaster *pBroadcaster;
-    SvtListener *pListener;
-
-public:
-
-    SvtListenerBase( SvtListener& rLst, SvtBroadcaster& rBroadcaster );
-    ~SvtListenerBase();
-
-    SvtListenerBase* GetNext() const        { return pNext; }
-    void SetNext( SvtListenerBase* p )      { pNext = p; }
-
-    SvtBroadcaster* GetBroadcaster() const  { return pBroadcaster; }
-    SvtListener* GetListener() const        { return pListener; }
-
-    SvtListenerBase* GetLeft() const        { return pLeft; }
-    SvtListenerBase* GetRight() const       { return pRight; }
-};
-
-
-#endif
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/notify/listeneriter.cxx b/svl/source/notify/listeneriter.cxx
deleted file mode 100644
index 79058da..0000000
--- a/svl/source/notify/listeneriter.cxx
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements. See the NOTICE file distributed
- *   with this work for additional information regarding copyright
- *   ownership. The ASF licenses this file to you under the Apache
- *   License, Version 2.0 (the "License"); you may not use this file
- *   except in compliance with the License. You may obtain a copy of
- *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-#include "listenerbase.hxx"
-#include <svl/listeneriter.hxx>
-#include <svl/broadcast.hxx>
-#include <svl/listener.hxx>
-
-SvtListenerIter* SvtListenerIter::pListenerIters = 0;
-
-SvtListenerIter::SvtListenerIter( SvtBroadcaster& rBrdcst )
-    : rRoot( rBrdcst )
-{
-    // hinten einketten!
-    pNxtIter = 0;
-    if( pListenerIters )
-    {
-        SvtListenerIter* pTmp = pListenerIters;
-        while( pTmp->pNxtIter )
-            pTmp = pTmp->pNxtIter;
-        pTmp->pNxtIter = this;
-    }
-    else
-        pListenerIters = this;
-
-    pAkt = rRoot.pRoot;
-    pDelNext = pAkt;
-}
-
-
-
-SvtListenerIter::~SvtListenerIter()
-{
-    if( pListenerIters )
-    {
-        if( pListenerIters == this )
-            pListenerIters = pNxtIter;
-        else
-        {
-            SvtListenerIter* pTmp = pListenerIters;
-            while( pTmp->pNxtIter != this )
-                if( 0 == ( pTmp = pTmp->pNxtIter ) )
-                    return ;
-            pTmp->pNxtIter = pNxtIter;
-        }
-    }
-}
-
-void SvtListenerIter::RemoveListener( SvtListenerBase& rDel,
-                                        SvtListenerBase* pNext )
-{
-    // Update the ListenerIter
-    SvtListenerIter* pTmp = pListenerIters;
-    while( pTmp )
-    {
-        if( pTmp->pAkt == &rDel || pTmp->pDelNext == &rDel )
-            pTmp->pDelNext = pNext;
-        pTmp = pTmp->pNxtIter;
-    }
-}
-
-SvtListener* SvtListenerIter::GoNext()
-{
-    if( pDelNext == pAkt )
-    {
-        pAkt = pAkt->GetRight();
-        pDelNext = pAkt;
-    }
-    else
-        pAkt = pDelNext;
-    return pAkt ? pAkt->GetListener() : 0;
-}
-
-SvtListener* SvtListenerIter::GoStart()         // zum Anfang des Baums
-{
-    pAkt = rRoot.pRoot;
-    if( pAkt )
-        while( pAkt->GetLeft() )
-            pAkt = pAkt->GetLeft();
-    pDelNext = pAkt;
-    return pAkt ? pAkt->GetListener() : 0;
-}
-
-SvtListener* SvtListenerIter::GetCurr() const   // returns the current
-{
-    return pDelNext ? pDelNext->GetListener() : 0;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list