diff options
author | Kohei Yoshida <kohei.yoshida@collabora.com> | 2013-11-14 21:20:12 -0500 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@collabora.com> | 2013-11-14 23:53:52 -0500 |
commit | 07f8216e5722d2288143367a07f4d567ab060431 (patch) | |
tree | 2b94cc96ff5322c912b697dff3dea04720eebc87 /sc | |
parent | 8819e6909568ec8e3feebb4226ef4f381af209a9 (diff) |
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
Diffstat (limited to 'sc')
-rw-r--r-- | sc/Library_sc.mk | 1 | ||||
-rw-r--r-- | sc/inc/compiler.hxx | 11 | ||||
-rw-r--r-- | sc/inc/document.hxx | 2 | ||||
-rw-r--r-- | sc/inc/tokenarray.hxx | 7 | ||||
-rw-r--r-- | sc/inc/tokenstringcontext.hxx | 39 | ||||
-rw-r--r-- | sc/qa/unit/ucalc.hxx | 2 | ||||
-rw-r--r-- | sc/qa/unit/ucalc_formula.cxx | 31 | ||||
-rw-r--r-- | sc/source/core/data/document.cxx | 16 | ||||
-rw-r--r-- | sc/source/core/tool/compiler.cxx | 191 | ||||
-rw-r--r-- | sc/source/core/tool/token.cxx | 158 | ||||
-rw-r--r-- | sc/source/core/tool/tokenstringcontext.cxx | 29 |
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: */ |