Resolves: tdf#135993 Create ScFunctionList and ScFuncDesc with English names
This is a combination of 4 commits.
Related: tdf#135993 Destroy temporary OpCodeMap when reading config
Initialized at FormulaCompiler base class instance it lacks AddIn
mapping and a still existing OpCodeMap prevents necessary
reinitialization from derived ScCompiler instance later.
xChange-Id: I0c2db41dd45829abfb8460730264f097ab76ab2e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137881
Tested-by: Jenkins
Reviewed-by: Eike Rathke <erack@redhat.com>
(cherry picked from commit 28c4c72a4e81821d9e567757725937f74a6d114f)
Related: tdf#135993 Use ScCompiler to create English OpCodeMap with AddIns
... instead of formula::FormulaCompiler base class that doesn't
know anything about AddIns, and copy AddIns along to new resulting
native map.
xChange-Id: I9e4ece2f7450a561ac502ca1dbddaa5a697fa2fe
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137882
Tested-by: Eike Rathke <erack@redhat.com>
Reviewed-by: Eike Rathke <erack@redhat.com>
(cherry picked from commit 0a78f11fdd13d914d5f063007b2df9796e6dce9d)
Resolves: tdf#135993 Create ScFunctionList and ScFuncDesc with English names
Used in Function Wizard and formula tooltips. Without, no matching
name is found for AddIn English name and no
tooltip/description/arguments are displayed.
xChange-Id: Ib0cf419c476dae495467c444f1ee1f84a55633a7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137883
Tested-by: Jenkins
Reviewed-by: Eike Rathke <erack@redhat.com>
(cherry picked from commit d778c6fd5c2ba8e27df46ec9e183a61ad29e30d5)
Use CharClass::uppercase() for AddIns' English UI names, tdf#135993 follow-up
... instead of OUString::toAsciiUpperCase(). English names should
consist of ASCII alphanumeric only, but we don't know what an
AddIn's author comes up with. Lookup in ScCompiler is done with
CharClass as well.
For this, use the static ScCompiler::GetCharClassEnglish()
instance made public and guard creation with a mutex.
xChange-Id: Icb79d49d4c7339c8d01b141de2a34715d794dd92
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138004
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
(cherry picked from commit 33c8c9d0dc8e76bc7dacb92175047a89f7d39a3c)
Change-Id: Ib0cf419c476dae495467c444f1ee1f84a55633a7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139229
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index be926e7..591b287 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -823,37 +823,37 @@ FormulaCompiler::OpCodeMapPtr FormulaCompiler::GetOpCodeMap( const sal_Int32 nLa
{
case FormulaLanguage::ODFF :
if (!mxSymbolsODFF)
InitSymbolsODFF();
InitSymbolsODFF( InitSymbols::INIT);
xMap = mxSymbolsODFF;
break;
case FormulaLanguage::ODF_11 :
if (!mxSymbolsPODF)
InitSymbolsPODF();
InitSymbolsPODF( InitSymbols::INIT);
xMap = mxSymbolsPODF;
break;
case FormulaLanguage::ENGLISH :
if (!mxSymbolsEnglish)
InitSymbolsEnglish();
InitSymbolsEnglish( InitSymbols::INIT);
xMap = mxSymbolsEnglish;
break;
case FormulaLanguage::NATIVE :
if (!mxSymbolsNative)
InitSymbolsNative();
InitSymbolsNative( InitSymbols::INIT);
xMap = mxSymbolsNative;
break;
case FormulaLanguage::XL_ENGLISH:
if (!mxSymbolsEnglishXL)
InitSymbolsEnglishXL();
InitSymbolsEnglishXL( InitSymbols::INIT);
xMap = mxSymbolsEnglishXL;
break;
case FormulaLanguage::OOXML:
if (!mxSymbolsOOXML)
InitSymbolsOOXML();
InitSymbolsOOXML( InitSymbols::INIT);
xMap = mxSymbolsOOXML;
break;
case FormulaLanguage::API :
if (!mxSymbolsAPI)
InitSymbolsAPI();
InitSymbolsAPI( InitSymbols::INIT);
xMap = mxSymbolsAPI;
break;
default:
@@ -862,6 +862,62 @@ FormulaCompiler::OpCodeMapPtr FormulaCompiler::GetOpCodeMap( const sal_Int32 nLa
return xMap;
}
void FormulaCompiler::DestroyOpCodeMap( const sal_Int32 nLanguage )
{
using namespace sheet;
switch (nLanguage)
{
case FormulaLanguage::ODFF :
InitSymbolsODFF( InitSymbols::DESTROY);
break;
case FormulaLanguage::ODF_11 :
InitSymbolsPODF( InitSymbols::DESTROY);
break;
case FormulaLanguage::ENGLISH :
InitSymbolsEnglish( InitSymbols::DESTROY);
break;
case FormulaLanguage::NATIVE :
InitSymbolsNative( InitSymbols::DESTROY);
break;
case FormulaLanguage::XL_ENGLISH:
InitSymbolsEnglishXL( InitSymbols::DESTROY);
break;
case FormulaLanguage::OOXML:
InitSymbolsOOXML( InitSymbols::DESTROY);
break;
case FormulaLanguage::API :
InitSymbolsAPI( InitSymbols::DESTROY);
break;
default:
; // nothing
}
}
bool FormulaCompiler::HasOpCodeMap( const sal_Int32 nLanguage ) const
{
using namespace sheet;
switch (nLanguage)
{
case FormulaLanguage::ODFF :
return InitSymbolsODFF( InitSymbols::ASK);
case FormulaLanguage::ODF_11 :
return InitSymbolsPODF( InitSymbols::ASK);
case FormulaLanguage::ENGLISH :
return InitSymbolsEnglish( InitSymbols::ASK);
case FormulaLanguage::NATIVE :
return InitSymbolsNative( InitSymbols::ASK);
case FormulaLanguage::XL_ENGLISH:
return InitSymbolsEnglishXL( InitSymbols::ASK);
case FormulaLanguage::OOXML:
return InitSymbolsOOXML( InitSymbols::ASK);
case FormulaLanguage::API :
return InitSymbolsAPI( InitSymbols::ASK);
default:
; // nothing
}
return false;
}
OUString FormulaCompiler::FindAddInFunction( const OUString& /*rUpperName*/, bool /*bLocalFirst*/ ) const
{
return OUString();
@@ -898,12 +954,16 @@ FormulaCompiler::OpCodeMapPtr FormulaCompiler::CreateOpCodeMap(
return xMap;
}
static void lcl_fillNativeSymbols( FormulaCompiler::NonConstOpCodeMapPtr& xMap, bool bDestroy = false )
static bool lcl_fillNativeSymbols( FormulaCompiler::NonConstOpCodeMapPtr& xMap, FormulaCompiler::InitSymbols eWhat = FormulaCompiler::InitSymbols::INIT )
{
static OpCodeMapData aSymbolMap;
osl::MutexGuard aGuard(&aSymbolMap.maMtx);
if ( bDestroy )
if (eWhat == FormulaCompiler::InitSymbols::ASK)
{
return bool(aSymbolMap.mxSymbolMap);
}
else if (eWhat == FormulaCompiler::InitSymbols::DESTROY)
{
aSymbolMap.mxSymbolMap.reset();
}
@@ -919,6 +979,8 @@ static void lcl_fillNativeSymbols( FormulaCompiler::NonConstOpCodeMapPtr& xMap,
}
xMap = aSymbolMap.mxSymbolMap;
return true;
}
const OUString& FormulaCompiler::GetNativeSymbol( OpCode eOp )
@@ -933,54 +995,80 @@ sal_Unicode FormulaCompiler::GetNativeSymbolChar( OpCode eOp )
return GetNativeSymbol(eOp)[0];
}
void FormulaCompiler::InitSymbolsNative() const
bool FormulaCompiler::InitSymbolsNative( FormulaCompiler::InitSymbols eWhat ) const
{
lcl_fillNativeSymbols( mxSymbolsNative);
return lcl_fillNativeSymbols( mxSymbolsNative, eWhat);
}
void FormulaCompiler::InitSymbolsEnglish() const
bool FormulaCompiler::InitSymbolsEnglish( FormulaCompiler::InitSymbols eWhat ) const
{
static OpCodeMapData aMap;
osl::MutexGuard aGuard(&aMap.maMtx);
if (!aMap.mxSymbolMap)
if (eWhat == InitSymbols::ASK)
return bool(aMap.mxSymbolMap);
else if (eWhat == InitSymbols::DESTROY)
aMap.mxSymbolMap.reset();
else if (!aMap.mxSymbolMap)
loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH, FormulaGrammar::GRAM_ENGLISH, aMap.mxSymbolMap);
mxSymbolsEnglish = aMap.mxSymbolMap;
return true;
}
void FormulaCompiler::InitSymbolsPODF() const
bool FormulaCompiler::InitSymbolsPODF( FormulaCompiler::InitSymbols eWhat ) const
{
static OpCodeMapData aMap;
osl::MutexGuard aGuard(&aMap.maMtx);
if (!aMap.mxSymbolMap)
if (eWhat == InitSymbols::ASK)
return bool(aMap.mxSymbolMap);
else if (eWhat == InitSymbols::DESTROY)
aMap.mxSymbolMap.reset();
else if (!aMap.mxSymbolMap)
loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH_PODF, FormulaGrammar::GRAM_PODF, aMap.mxSymbolMap, SeparatorType::RESOURCE_BASE);
mxSymbolsPODF = aMap.mxSymbolMap;
return true;
}
void FormulaCompiler::InitSymbolsAPI() const
bool FormulaCompiler::InitSymbolsAPI( FormulaCompiler::InitSymbols eWhat ) const
{
static OpCodeMapData aMap;
osl::MutexGuard aGuard(&aMap.maMtx);
if (!aMap.mxSymbolMap)
if (eWhat == InitSymbols::ASK)
return bool(aMap.mxSymbolMap);
else if (eWhat == InitSymbols::DESTROY)
aMap.mxSymbolMap.reset();
else if (!aMap.mxSymbolMap)
loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH_API, FormulaGrammar::GRAM_API, aMap.mxSymbolMap, SeparatorType::RESOURCE_BASE);
mxSymbolsAPI = aMap.mxSymbolMap;
return true;
}
void FormulaCompiler::InitSymbolsODFF() const
bool FormulaCompiler::InitSymbolsODFF( FormulaCompiler::InitSymbols eWhat ) const
{
static OpCodeMapData aMap;
osl::MutexGuard aGuard(&aMap.maMtx);
if (!aMap.mxSymbolMap)
if (eWhat == InitSymbols::ASK)
return bool(aMap.mxSymbolMap);
else if (eWhat == InitSymbols::DESTROY)
aMap.mxSymbolMap.reset();
else if (!aMap.mxSymbolMap)
loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF, FormulaGrammar::GRAM_ODFF, aMap.mxSymbolMap, SeparatorType::RESOURCE_BASE);
mxSymbolsODFF = aMap.mxSymbolMap;
return true;
}
void FormulaCompiler::InitSymbolsEnglishXL() const
bool FormulaCompiler::InitSymbolsEnglishXL( FormulaCompiler::InitSymbols eWhat ) const
{
static OpCodeMapData aMap;
osl::MutexGuard aGuard(&aMap.maMtx);
if (!aMap.mxSymbolMap)
if (eWhat == InitSymbols::ASK)
return bool(aMap.mxSymbolMap);
else if (eWhat == InitSymbols::DESTROY)
aMap.mxSymbolMap.reset();
else if (!aMap.mxSymbolMap)
loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH, FormulaGrammar::GRAM_ENGLISH, aMap.mxSymbolMap);
mxSymbolsEnglishXL = aMap.mxSymbolMap;
if (eWhat != InitSymbols::INIT)
return true;
// TODO: For now, just replace the separators to the Excel English
// variants. Later, if we want to properly map Excel functions with Calc
@@ -988,15 +1076,22 @@ void FormulaCompiler::InitSymbolsEnglishXL() const
mxSymbolsEnglishXL->putOpCode( OUString(','), ocSep, nullptr);
mxSymbolsEnglishXL->putOpCode( OUString(','), ocArrayColSep, nullptr);
mxSymbolsEnglishXL->putOpCode( OUString(';'), ocArrayRowSep, nullptr);
return true;
}
void FormulaCompiler::InitSymbolsOOXML() const
bool FormulaCompiler::InitSymbolsOOXML( FormulaCompiler::InitSymbols eWhat ) const
{
static OpCodeMapData aMap;
osl::MutexGuard aGuard(&aMap.maMtx);
if (!aMap.mxSymbolMap)
if (eWhat == InitSymbols::ASK)
return bool(aMap.mxSymbolMap);
else if (eWhat == InitSymbols::DESTROY)
aMap.mxSymbolMap.reset();
else if (!aMap.mxSymbolMap)
loadSymbols(RID_STRLIST_FUNCTION_NAMES_ENGLISH_OOXML, FormulaGrammar::GRAM_OOXML, aMap.mxSymbolMap, SeparatorType::RESOURCE_BASE);
mxSymbolsOOXML = aMap.mxSymbolMap;
return true;
}
@@ -1201,7 +1296,16 @@ void FormulaCompiler::OpCodeMap::copyFrom( const OpCodeMap& r )
}
}
// TODO: maybe copy the external maps too?
// This was meant to copy to native map that does not have AddIn symbols
// but needs them from the source map. It is unclear what should happen if
// the destination already had externals, so do it only if it doesn't.
if (!hasExternals())
{
maExternalHashMap = r.maExternalHashMap;
maReverseExternalHashMap = r.maReverseExternalHashMap;
mbCore = r.mbCore;
mbEnglish = r.mbEnglish;
}
}
@@ -2588,7 +2692,7 @@ void FormulaCompiler::UpdateSeparatorsNative(
void FormulaCompiler::ResetNativeSymbols()
{
NonConstOpCodeMapPtr xSymbolsNative;
lcl_fillNativeSymbols( xSymbolsNative, true);
lcl_fillNativeSymbols( xSymbolsNative, InitSymbols::DESTROY);
lcl_fillNativeSymbols( xSymbolsNative);
}
diff --git a/include/formula/FormulaCompiler.hxx b/include/formula/FormulaCompiler.hxx
index 5544ff8..3663203 100644
--- a/include/formula/FormulaCompiler.hxx
+++ b/include/formula/FormulaCompiler.hxx
@@ -203,6 +203,26 @@ public:
*/
OpCodeMapPtr GetOpCodeMap( const sal_Int32 nLanguage ) const;
/** Destroy the singleton OpCodeMap for formula language.
This unconditionally destroys the underlying singleton instance of the
map to be reinitialized again later on the next GetOpCodeMap() call.
Use if the base class FormulaCompiler::GetOpCodeMap() was called and
created the map (i.e. HasOpCodeMap() before returned false) and later a
derived class like ScCompiler shall initialize it including AddIns.
@param nLanguage
One of css::sheet::FormulaLanguage constants.
*/
void DestroyOpCodeMap( const sal_Int32 nLanguage );
/** Whether the singleton OpCodeMap for formula language exists already.
@param nLanguage
One of css::sheet::FormulaLanguage constants.
*/
bool HasOpCodeMap( const sal_Int32 nLanguage ) const;
/** Create an internal symbol map from API mapping.
@param bEnglish
Use English number parser / formatter instead of native.
@@ -370,14 +390,22 @@ protected:
bool mbComputeII; // whether to attempt computing implicit intersection ranges while building the RPN array.
bool mbMatrixFlag; // whether the formula is a matrix formula (needed for II computation)
public:
enum InitSymbols
{
ASK = 0,
INIT,
DESTROY
};
private:
void InitSymbolsNative() const; /// only SymbolsNative, on first document creation
void InitSymbolsEnglish() const; /// only SymbolsEnglish, maybe later
void InitSymbolsPODF() const; /// only SymbolsPODF, on demand
void InitSymbolsAPI() const; /// only SymbolsAPI, on demand
void InitSymbolsODFF() const; /// only SymbolsODFF, on demand
void InitSymbolsEnglishXL() const; /// only SymbolsEnglishXL, on demand
void InitSymbolsOOXML() const; /// only SymbolsOOXML, on demand
bool InitSymbolsNative( InitSymbols ) const; /// only SymbolsNative, on first document creation
bool InitSymbolsEnglish( InitSymbols ) const; /// only SymbolsEnglish, maybe later
bool InitSymbolsPODF( InitSymbols ) const; /// only SymbolsPODF, on demand
bool InitSymbolsAPI( InitSymbols ) const; /// only SymbolsAPI, on demand
bool InitSymbolsODFF( InitSymbols ) const; /// only SymbolsODFF, on demand
bool InitSymbolsEnglishXL( InitSymbols ) const; /// only SymbolsEnglishXL, on demand
bool InitSymbolsOOXML( InitSymbols ) const; /// only SymbolsOOXML, on demand
void loadSymbols(const std::pair<const char*, int>* pSymbols, FormulaGrammar::Grammar eGrammar, NonConstOpCodeMapPtr& rxMap,
SeparatorType eSepType = SeparatorType::SEMICOLON_BASE) const;
diff --git a/sc/inc/addincol.hxx b/sc/inc/addincol.hxx
index 14af120..bb89f8d 100644
--- a/sc/inc/addincol.hxx
+++ b/sc/inc/addincol.hxx
@@ -87,6 +87,7 @@ private:
OUString aLocalName; ///< for display
OUString aUpperName; ///< for entering formulas
OUString aUpperLocal; ///< for entering formulas
OUString aUpperEnglish; ///< for Function Wizard and tooltips
OUString aDescription;
css::uno::Reference< css::reflection::XIdlMethod> xFunction;
css::uno::Any aObject;
@@ -113,6 +114,7 @@ public:
const OUString& GetLocalName() const { return aLocalName; }
const OUString& GetUpperName() const { return aUpperName; }
const OUString& GetUpperLocal() const { return aUpperLocal; }
const OUString& GetUpperEnglish() const { return aUpperEnglish; }
const css::uno::Reference< css::reflection::XIdlMethod>& GetFunction() const
{ return xFunction; }
const css::uno::Any& GetObject() const { return aObject; }
@@ -132,6 +134,9 @@ public:
void SetArguments( tools::Long nNewCount, const ScAddInArgDesc* pNewDescs );
void SetCallerPos( tools::Long nNewPos );
void SetCompNames( ::std::vector< LocalizedName >&& rNew );
/// Takes care of handling an empty name *after* upper local name was set.
void SetEnglishName( const OUString& rEnglishName );
};
class SC_DLLPUBLIC ScUnoAddInCollection
@@ -175,9 +180,10 @@ public:
void LocalizeString( OUString& rName ); ///< modify rName - input: exact name
tools::Long GetFuncCount();
bool FillFunctionDesc( tools::Long nFunc, ScFuncDesc& rDesc );
bool FillFunctionDesc( tools::Long nFunc, ScFuncDesc& rDesc, bool bEnglishFunctionNames );
static bool FillFunctionDescFromData( const ScUnoAddInFuncData& rFuncData, ScFuncDesc& rDesc );
static bool FillFunctionDescFromData( const ScUnoAddInFuncData& rFuncData, ScFuncDesc& rDesc,
bool bEnglishFunctionNames );
/// leave rRetExcelName unchanged, if no matching name is found
bool GetExcelName( const OUString& rCalcName, LanguageType eDestLang, OUString& rRetExcelName );
/// leave rRetCalcName unchanged, if no matching name is found
diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx
index 0cd48fc..5f6c521 100644
--- a/sc/inc/compiler.hxx
+++ b/sc/inc/compiler.hxx
@@ -257,6 +257,7 @@ public:
private:
static osl::Mutex maMutex;
static const CharClass *pCharClassEnglish; // character classification for en_US locale
static const CharClass *pCharClassLocalized; // character classification for UI locale
static const Convention *pConventions[ formula::FormulaGrammar::CONV_LAST ];
@@ -377,8 +378,9 @@ private:
bool HasPossibleNamedRangeConflict(SCTAB nTab) const;
static const CharClass* GetCharClassEnglish();
static const CharClass* GetCharClassLocalized();
public:
static const CharClass* GetCharClassEnglish();
public:
ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& rPos,
diff --git a/sc/inc/funcdesc.hxx b/sc/inc/funcdesc.hxx
index 58c6957..0f37e92 100644
--- a/sc/inc/funcdesc.hxx
+++ b/sc/inc/funcdesc.hxx
@@ -241,7 +241,7 @@ public:
class ScFunctionList
{
public:
ScFunctionList();
explicit ScFunctionList( bool bEnglishFunctionNames );
~ScFunctionList();
sal_uInt32 GetCount() const
diff --git a/sc/source/core/data/funcdesc.cxx b/sc/source/core/data/funcdesc.cxx
index dfbfd9a..c8045e6 100644
--- a/sc/source/core/data/funcdesc.cxx
+++ b/sc/source/core/data/funcdesc.cxx
@@ -397,7 +397,7 @@ bool ScFuncDesc::compareByName(const ScFuncDesc* a, const ScFuncDesc* b)
#define ENTRY(CODE) CODE, SAL_N_ELEMENTS(CODE)
ScFunctionList::ScFunctionList()
ScFunctionList::ScFunctionList( bool bEnglishFunctionNames )
{
sal_Int32 nMaxFuncNameLen = 0; // Length of longest function name
@@ -958,7 +958,7 @@ ScFunctionList::ScFunctionList()
pDesc = new ScFuncDesc;
pDesc->nFIndex = nNextId++;
if ( pUnoAddIns->FillFunctionDesc( nFunc, *pDesc ) )
if ( pUnoAddIns->FillFunctionDesc( nFunc, *pDesc, bEnglishFunctionNames ) )
{
tmpFuncVector.push_back(pDesc);
nStrLen = pDesc->mxFuncName->getLength();
diff --git a/sc/source/core/data/global.cxx b/sc/source/core/data/global.cxx
index a338c0c..46277a8 100644
--- a/sc/source/core/data/global.cxx
+++ b/sc/source/core/data/global.cxx
@@ -74,6 +74,7 @@
#include <editutil.hxx>
#include <docsh.hxx>
#include <sharedstringpoolpurge.hxx>
#include <formulaopt.hxx>
tools::SvRef<ScDocShell> ScGlobal::xDrawClipDocShellRef;
std::unique_ptr<SvxSearchItem> ScGlobal::xSearchItem;
@@ -621,7 +622,7 @@ ScFunctionList* ScGlobal::GetStarCalcFunctionList()
{
assert(!bThreadedGroupCalcInProgress);
if ( !xStarCalcFunctionList )
xStarCalcFunctionList.reset(new ScFunctionList);
xStarCalcFunctionList.reset( new ScFunctionList( SC_MOD()->GetFormulaOptions().GetUseEnglishFuncName()));
return xStarCalcFunctionList.get();
}
diff --git a/sc/source/core/tool/addincol.cxx b/sc/source/core/tool/addincol.cxx
index ea21842..9027f04 100644
--- a/sc/source/core/tool/addincol.cxx
+++ b/sc/source/core/tool/addincol.cxx
@@ -59,6 +59,7 @@
#include <funcdesc.hxx>
#include <svl/sharedstring.hxx>
#include <formulaopt.hxx>
#include <compiler.hxx>
#include <memory>
using namespace com::sun::star;
@@ -138,6 +139,19 @@ void ScUnoAddInFuncData::SetCompNames( ::std::vector< ScUnoAddInFuncData::Locali
bCompInitialized = true;
}
void ScUnoAddInFuncData::SetEnglishName( const OUString& rEnglishName )
{
if (!rEnglishName.isEmpty())
aUpperEnglish = ScCompiler::GetCharClassEnglish()->uppercase(rEnglishName);
else
{
// A dumb fallback to not have an empty name, mainly just for the
// assignment to ScFuncDesc::mxFuncName for the Function Wizard and
// formula input tooltips.
aUpperEnglish = aUpperLocal;
}
}
bool ScUnoAddInFuncData::GetExcelName( const LanguageTag& rDestLang, OUString& rRetExcelName, bool bFallbackToAny ) const
{
const ::std::vector<LocalizedName>& rCompNames = GetCompNames();
@@ -544,9 +558,10 @@ void ScUnoAddInCollection::ReadConfiguration()
else
{
pEnglishHashMap->emplace(
aEnglishName.toAsciiUpperCase(),
ScCompiler::GetCharClassEnglish()->uppercase(aEnglishName),
pData );
}
pData->SetEnglishName(aEnglishName); // takes care of handling empty
}
}
}
@@ -720,12 +735,11 @@ void ScUnoAddInCollection::ReadFromAddIn( const uno::Reference<uno::XInterface>&
if ( !(xAddIn.is() && xName.is()) )
return;
// fdo50118 when GetUseEnglishFunctionName() returns true, set the
// locale to en-US to get English function names
if ( SC_MOD()->GetFormulaOptions().GetUseEnglishFuncName() )
xAddIn->setLocale( lang::Locale( "en", "US", ""));
else
xAddIn->setLocale( Application::GetSettings().GetUILanguageTag().getLocale());
// Even if GetUseEnglishFunctionName() would return true, do not set the
// locale to en-US to get English function names as that also would mix in
// English descriptions and parameter names. English function names are now
// handled below.
xAddIn->setLocale( Application::GetSettings().GetUILanguageTag().getLocale());
OUString aServiceName( xName->getServiceName() );
ScUnoAddInHelpIdGenerator aHelpIdGenerator( aServiceName );
@@ -919,8 +933,7 @@ void ScUnoAddInCollection::ReadFromAddIn( const uno::Reference<uno::XInterface>&
xFunc, aObject,
nVisibleCount, pVisibleArgs.get(), nCallerPos ) );
const ScUnoAddInFuncData* pData =
ppFuncData[nFuncPos+nOld].get();
ScUnoAddInFuncData* pData = ppFuncData[nFuncPos+nOld].get();
pExactHashMap->emplace(
pData->GetOriginalName(),
pData );
@@ -937,18 +950,21 @@ void ScUnoAddInCollection::ReadFromAddIn( const uno::Reference<uno::XInterface>&
else
{
pEnglishHashMap->emplace(
aEnglishName.toAsciiUpperCase(),
ScCompiler::GetCharClassEnglish()->uppercase(aEnglishName),
pData );
}
pData->SetEnglishName(aEnglishName); // takes care of handling empty
}
}
}
}
}
static void lcl_UpdateFunctionList( const ScFunctionList& rFunctionList, const ScUnoAddInFuncData& rFuncData )
static void lcl_UpdateFunctionList( const ScFunctionList& rFunctionList, const ScUnoAddInFuncData& rFuncData,
bool bEnglishFunctionNames )
{
const OUString& aCompare = rFuncData.GetUpperLocal(); // as used in FillFunctionDescFromData
// as used in FillFunctionDescFromData
const OUString& aCompare = (bEnglishFunctionNames ? rFuncData.GetUpperEnglish() : rFuncData.GetUpperLocal());
sal_uLong nCount = rFunctionList.GetCount();
for (sal_uLong nPos=0; nPos<nCount; nPos++)
@@ -956,7 +972,8 @@ static void lcl_UpdateFunctionList( const ScFunctionList& rFunctionList, const S
const ScFuncDesc* pDesc = rFunctionList.GetFunction( nPos );
if ( pDesc && pDesc->mxFuncName && *pDesc->mxFuncName == aCompare )
{
ScUnoAddInCollection::FillFunctionDescFromData( rFuncData, *const_cast<ScFuncDesc*>(pDesc) );
ScUnoAddInCollection::FillFunctionDescFromData( rFuncData, *const_cast<ScFuncDesc*>(pDesc),
bEnglishFunctionNames);
break;
}
}
@@ -977,16 +994,10 @@ static const ScAddInArgDesc* lcl_FindArgDesc( const ScUnoAddInFuncData& rFuncDat
void ScUnoAddInCollection::UpdateFromAddIn( const uno::Reference<uno::XInterface>& xInterface,
std::u16string_view rServiceName )
{
const bool bEnglishFunctionNames = SC_MOD()->GetFormulaOptions().GetUseEnglishFuncName();
uno::Reference<lang::XLocalizable> xLoc( xInterface, uno::UNO_QUERY );
if ( xLoc.is() ) // optional in new add-ins
{
// fdo50118 when GetUseEnglishFunctionName() returns true, set the
// locale to en-US to get English function names
if ( SC_MOD()->GetFormulaOptions().GetUseEnglishFuncName() )
xLoc->setLocale( lang::Locale( "en", "US", ""));
else
xLoc->setLocale( Application::GetSettings().GetUILanguageTag().getLocale());
}
xLoc->setLocale( Application::GetSettings().GetUILanguageTag().getLocale());
// if function list was already initialized, it must be updated
@@ -1092,7 +1103,7 @@ void ScUnoAddInCollection::UpdateFromAddIn( const uno::Reference<uno::XInterface
pOldData->SetCallerPos( nCallerPos );
if ( pFunctionList )
lcl_UpdateFunctionList( *pFunctionList, *pOldData );
lcl_UpdateFunctionList( *pFunctionList, *pOldData, bEnglishFunctionNames );
}
}
}
@@ -1193,7 +1204,7 @@ tools::Long ScUnoAddInCollection::GetFuncCount()
return nFuncCount;
}
bool ScUnoAddInCollection::FillFunctionDesc( tools::Long nFunc, ScFuncDesc& rDesc )
bool ScUnoAddInCollection::FillFunctionDesc( tools::Long nFunc, ScFuncDesc& rDesc, bool bEnglishFunctionNames )
{
if (!bInitialized)
Initialize();
@@ -1203,10 +1214,11 @@ bool ScUnoAddInCollection::FillFunctionDesc( tools::Long nFunc, ScFuncDesc& rDes
const ScUnoAddInFuncData& rFuncData = *ppFuncData[nFunc];
return FillFunctionDescFromData( rFuncData, rDesc );
return FillFunctionDescFromData( rFuncData, rDesc, bEnglishFunctionNames );
}
bool ScUnoAddInCollection::FillFunctionDescFromData( const ScUnoAddInFuncData& rFuncData, ScFuncDesc& rDesc )
bool ScUnoAddInCollection::FillFunctionDescFromData( const ScUnoAddInFuncData& rFuncData, ScFuncDesc& rDesc,
bool bEnglishFunctionNames )
{
rDesc.Clear();
@@ -1221,7 +1233,7 @@ bool ScUnoAddInCollection::FillFunctionDescFromData( const ScUnoAddInFuncData& r
// nFIndex is set from outside
rDesc.mxFuncName = rFuncData.GetUpperLocal(); //TODO: upper?
rDesc.mxFuncName = (bEnglishFunctionNames ? rFuncData.GetUpperEnglish() : rFuncData.GetUpperLocal());
rDesc.nCategory = rFuncData.GetCategory();
rDesc.sHelpId = rFuncData.GetHelpId();
diff --git a/sc/source/core/tool/calcconfig.cxx b/sc/source/core/tool/calcconfig.cxx
index f1673e0..2783670 100644
--- a/sc/source/core/tool/calcconfig.cxx
+++ b/sc/source/core/tool/calcconfig.cxx
@@ -187,7 +187,11 @@ bool ScCalcConfig::operator!= (const ScCalcConfig& r) const
OUString ScOpCodeSetToSymbolicString(const ScCalcConfig::OpCodeSet& rOpCodes)
{
OUStringBuffer result(256);
// If GetOpCodeMap() initializes the map at base class
// formula::FormulaCompiler before any ScCompiler did, all AddIn mapping
// would be missing also in future. So if it didn't exist destroy it again.
formula::FormulaCompiler aCompiler;
const bool bTemporary = !aCompiler.HasOpCodeMap(css::sheet::FormulaLanguage::ENGLISH);
formula::FormulaCompiler::OpCodeMapPtr pOpCodeMap(aCompiler.GetOpCodeMap(css::sheet::FormulaLanguage::ENGLISH));
for (auto i = rOpCodes->begin(); i != rOpCodes->end(); ++i)
@@ -197,13 +201,18 @@ OUString ScOpCodeSetToSymbolicString(const ScCalcConfig::OpCodeSet& rOpCodes)
result.append(pOpCodeMap->getSymbol(*i));
}
if (bTemporary)
aCompiler.DestroyOpCodeMap(css::sheet::FormulaLanguage::ENGLISH);
return result.makeStringAndClear();
}
ScCalcConfig::OpCodeSet ScStringToOpCodeSet(std::u16string_view rOpCodes)
{
ScCalcConfig::OpCodeSet result = std::make_shared<o3tl::sorted_vector< OpCode >>();
// Same as above.
formula::FormulaCompiler aCompiler;
const bool bTemporary = !aCompiler.HasOpCodeMap(css::sheet::FormulaLanguage::ENGLISH);
formula::FormulaCompiler::OpCodeMapPtr pOpCodeMap(aCompiler.GetOpCodeMap(css::sheet::FormulaLanguage::ENGLISH));
const formula::OpCodeHashMap& rHashMap(pOpCodeMap->getHashMap());
@@ -234,6 +243,10 @@ ScCalcConfig::OpCodeSet ScStringToOpCodeSet(std::u16string_view rOpCodes)
// HACK: Both unary and binary minus have the same string but different opcodes.
if( result->find( ocSub ) != result->end())
result->insert( ocNegSub );
if (bTemporary)
aCompiler.DestroyOpCodeMap(css::sheet::FormulaLanguage::ENGLISH);
return result;
}
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index d7b6286..b6784f8 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -77,6 +77,7 @@ using namespace formula;
using namespace ::com::sun::star;
using ::std::vector;
osl::Mutex ScCompiler::maMutex;
const CharClass* ScCompiler::pCharClassEnglish = nullptr;
const CharClass* ScCompiler::pCharClassLocalized = nullptr;
const ScCompiler::Convention* ScCompiler::pConventions[ ] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
@@ -225,9 +226,12 @@ const CharClass* ScCompiler::GetCharClassEnglish()
{
if (!pCharClassEnglish)
{
css::lang::Locale aLocale( "en", "US", "");
pCharClassEnglish = new CharClass(
::comphelper::getProcessComponentContext(), LanguageTag( aLocale));
osl::MutexGuard aGuard(maMutex);
if (!pCharClassEnglish)
{
pCharClassEnglish = new CharClass( ::comphelper::getProcessComponentContext(),
LanguageTag( LANGUAGE_ENGLISH_US));
}
}
return pCharClassEnglish;
}
diff --git a/sc/source/ui/docshell/docsh6.cxx b/sc/source/ui/docshell/docsh6.cxx
index 738c8511..caefdfc 100644
--- a/sc/source/ui/docshell/docsh6.cxx
+++ b/sc/source/ui/docshell/docsh6.cxx
@@ -445,7 +445,8 @@ void ScDocShell::SetFormulaOptions( const ScFormulaOptions& rOpt, bool bForLoadi
if (rOpt.GetUseEnglishFuncName())
{
// switch native symbols to English.
formula::FormulaCompiler aComp;
ScAddress aAddress;
ScCompiler aComp( *m_pDocument, aAddress);
ScCompiler::OpCodeMapPtr xMap = aComp.GetOpCodeMap(css::sheet::FormulaLanguage::ENGLISH);
ScCompiler::SetNativeSymbols(xMap);
}