summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sc/Library_sc.mk1
-rw-r--r--sc/inc/compiler.hxx11
-rw-r--r--sc/inc/document.hxx2
-rw-r--r--sc/inc/tokenarray.hxx7
-rw-r--r--sc/inc/tokenstringcontext.hxx39
-rw-r--r--sc/qa/unit/ucalc.hxx2
-rw-r--r--sc/qa/unit/ucalc_formula.cxx31
-rw-r--r--sc/source/core/data/document.cxx16
-rw-r--r--sc/source/core/tool/compiler.cxx191
-rw-r--r--sc/source/core/tool/token.cxx158
-rw-r--r--sc/source/core/tool/tokenstringcontext.cxx29
11 files changed, 403 insertions, 84 deletions
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 5754ad9b4a76..c9f0b5fbcf1f 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 4cd31a3ab6b0..6844b283e840 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 09f14665aafa..68e57d2900c6 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 83a3988d4643..b8aec07b2354 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 000000000000..e5bb01c3ccc9
--- /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 19c94d747c9f..1298e73e62a8 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 d12e45dd13f6..c780717fed8c 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 f8a6d922c640..80696e4bd0ed 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 664145199586..1ef766c995af 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 3d99294cb672..c9377a288549 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 000000000000..5fea0a9837d9
--- /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: */