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.

Change-Id: Ib0cf419c476dae495467c444f1ee1f84a55633a7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137883
Tested-by: Jenkins
Reviewed-by: Eike Rathke <erack@redhat.com>
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/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..2c756a1 100644
--- a/sc/source/core/tool/addincol.cxx
+++ b/sc/source/core/tool/addincol.cxx
@@ -138,6 +138,19 @@ void ScUnoAddInFuncData::SetCompNames( ::std::vector< ScUnoAddInFuncData::Locali
    bCompInitialized = true;
}

void ScUnoAddInFuncData::SetEnglishName( const OUString& rEnglishName )
{
    if (!rEnglishName.isEmpty())
        aUpperEnglish = rEnglishName.toAsciiUpperCase();
    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();
@@ -547,6 +560,7 @@ void ScUnoAddInCollection::ReadConfiguration()
                            aEnglishName.toAsciiUpperCase(),
                            pData );
                }
                pData->SetEnglishName(aEnglishName);    // takes care of handling empty
            }
        }
    }
@@ -720,12 +734,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 +932,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 );
@@ -940,15 +952,18 @@ void ScUnoAddInCollection::ReadFromAddIn( const uno::Reference<uno::XInterface>&
                                aEnglishName.toAsciiUpperCase(),
                                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 +971,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 +993,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 +1102,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 +1203,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 +1213,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 +1232,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();