Resolves: tdf#150203 Gather AddIn English names and provide for FunctionAccess

This works at least for the bundled AddIns from scaddins/. It may
for others if en-US compatibility function names are provided, if
not the local name will be continued to be used.

Change-Id: I09e23f731c0f3d9753ef355ab59c2005bc567464
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137708
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
diff --git a/sc/inc/addincol.hxx b/sc/inc/addincol.hxx
index 9366e31..2602624 100644
--- a/sc/inc/addincol.hxx
+++ b/sc/inc/addincol.hxx
@@ -123,7 +123,8 @@ public:
    const OString&          GetHelpId() const           { return sHelpId; }

    const ::std::vector< LocalizedName >&  GetCompNames() const;
    bool                    GetExcelName( LanguageType eDestLang, OUString& rRetExcelName ) const;
    bool                    GetExcelName( LanguageType eDestLang, OUString& rRetExcelName,
                                          bool bFallbackToAny = true ) const;

    void    SetFunction( const css::uno::Reference< css::reflection::XIdlMethod>& rNewFunc,
                         const css::uno::Any& rNewObj );
@@ -140,6 +141,7 @@ private:
    std::unique_ptr<ScAddInHashMap>       pExactHashMap;      ///< exact internal name
    std::unique_ptr<ScAddInHashMap>       pNameHashMap;       ///< internal name upper
    std::unique_ptr<ScAddInHashMap>       pLocalHashMap;      ///< localized name upper
    std::unique_ptr<ScAddInHashMap>       pEnglishHashMap;    ///< English name upper
    bool                    bInitialized;

    void        Initialize();
diff --git a/sc/source/core/tool/addincol.cxx b/sc/source/core/tool/addincol.cxx
index addb151..7ccf8b6 100644
--- a/sc/source/core/tool/addincol.cxx
+++ b/sc/source/core/tool/addincol.cxx
@@ -138,7 +138,7 @@ void ScUnoAddInFuncData::SetCompNames( ::std::vector< ScUnoAddInFuncData::Locali
    bCompInitialized = true;
}

bool ScUnoAddInFuncData::GetExcelName( LanguageType eDestLang, OUString& rRetExcelName ) const
bool ScUnoAddInFuncData::GetExcelName( LanguageType eDestLang, OUString& rRetExcelName, bool bFallbackToAny ) const
{
    const ::std::vector<LocalizedName>& rCompNames = GetCompNames();
    if ( !rCompNames.empty() )
@@ -180,9 +180,12 @@ bool ScUnoAddInFuncData::GetExcelName( LanguageType eDestLang, OUString& rRetExc
            }
        }

        // Third, last resort, use first (default) entry.
        rRetExcelName = rCompNames[0].maName;
        return true;
        if (bFallbackToAny)
        {
            // Third, last resort, use first (default) entry.
            rRetExcelName = rCompNames[0].maName;
            return true;
        }
    }
    return false;
}
@@ -226,6 +229,7 @@ void ScUnoAddInCollection::Clear()
    pExactHashMap.reset();
    pNameHashMap.reset();
    pLocalHashMap.reset();
    pEnglishHashMap.reset();
    ppFuncData.reset();
    nFuncCount = 0;

@@ -380,6 +384,8 @@ void ScUnoAddInCollection::ReadConfiguration()
            pNameHashMap.reset( new ScAddInHashMap );
        if ( !pLocalHashMap )
            pLocalHashMap.reset( new ScAddInHashMap );
        if ( !pEnglishHashMap )
            pEnglishHashMap.reset( new ScAddInHashMap );

        //TODO: get the function information in a single call for all functions?

@@ -395,6 +401,7 @@ void ScUnoAddInCollection::ReadConfiguration()

            if ( pExactHashMap->find( aFuncName ) == pExactHashMap->end() )
            {
                OUString aEnglishName;
                OUString aLocalName;
                OUString aDescription;
                sal_uInt16 nCategory = ID_FUNCTION_GRP_ADDINS;
@@ -441,6 +448,11 @@ void ScUnoAddInCollection::ReadConfiguration()
                            OUString aName;
                            rConfig.Value >>= aName;
                            aCompNames.emplace_back( aLocale, aName);
                            // Accept 'en' and 'en-...' but prefer 'en-US'.
                            if (aLocale == "en-US")
                                aEnglishName = aName;
                            else if (aEnglishName.isEmpty() && (aLocale == "en" || aLocale.startsWith("en-")))
                                aEnglishName = aName;
                        }
                    }
                }
@@ -527,6 +539,15 @@ void ScUnoAddInCollection::ReadConfiguration()
                pLocalHashMap->emplace(
                            pData->GetUpperLocal(),
                            pData );

                if (aEnglishName.isEmpty())
                    SAL_WARN("sc.core", "no English name for " << aLocalName << " " << aFuncName);
                else
                {
                    pEnglishHashMap->emplace(
                            aEnglishName.toAsciiUpperCase(),
                            pData );
                }
            }
        }
    }
@@ -746,6 +767,8 @@ void ScUnoAddInCollection::ReadFromAddIn( const uno::Reference<uno::XInterface>&
        pNameHashMap.reset( new ScAddInHashMap );
    if ( !pLocalHashMap )
        pLocalHashMap.reset( new ScAddInHashMap );
    if ( !pEnglishHashMap )
        pEnglishHashMap.reset( new ScAddInHashMap );

    const uno::Reference<reflection::XIdlMethod>* pArray = aMethods.getConstArray();
    for (tools::Long nFuncPos=0; nFuncPos<nNewCount; nFuncPos++)
@@ -907,6 +930,16 @@ void ScUnoAddInCollection::ReadFromAddIn( const uno::Reference<uno::XInterface>&
                    pLocalHashMap->emplace(
                                pData->GetUpperLocal(),
                                pData );

                    OUString aEnglishName;
                    if (!pData->GetExcelName( LANGUAGE_ENGLISH_US, aEnglishName, false /*bFallbackToAny*/))
                        SAL_WARN("sc.core", "no English name for " << aLocalName << " " << aFuncName);
                    else
                    {
                        pEnglishHashMap->emplace(
                                aEnglishName.toAsciiUpperCase(),
                                pData );
                    }
                }
            }
        }
@@ -1076,7 +1109,7 @@ OUString ScUnoAddInCollection::FindFunction( const OUString& rUpperName, bool bL

    if ( bLocalFirst )
    {
        //  first scan all local names (used for entering formulas)
        // Only scan local names (used for entering formulas).

        ScAddInHashMap::const_iterator iLook( pLocalHashMap->find( rUpperName ) );
        if ( iLook != pLocalHashMap->end() )
@@ -1084,14 +1117,22 @@ OUString ScUnoAddInCollection::FindFunction( const OUString& rUpperName, bool bL
    }
    else
    {
        //  first scan international names (used when calling a function)
        //TODO: before that, check for exact match???
        // First scan international programmatic names (used when calling a
        // function).

        ScAddInHashMap::const_iterator iLook( pNameHashMap->find( rUpperName ) );
        if ( iLook != pNameHashMap->end() )
            return iLook->second->GetOriginalName();

        //  after that, scan all local names (to allow replacing old AddIns with Uno)
        // Then scan English names (as FunctionAccess API could expect).

        iLook = pEnglishHashMap->find( rUpperName );
        if ( iLook != pEnglishHashMap->end() )
            return iLook->second->GetOriginalName();

        // After that, scan all local names; either to allow replacing old
        // AddIns with Uno, or for functions where the AddIn did not provide an
        // English name.

        iLook = pLocalHashMap->find( rUpperName );
        if ( iLook != pLocalHashMap->end() )