tdf#142031 - Collect all the characters for the formula suggestion auto input

This is a combination of 5 commits.

tdf#142031 - Collect all the characters for the formula suggestion auto input

Change-Id: Idec350b09279f42f2ca42a1c02082d8e9e4207b8
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138702
Tested-by: Jenkins
Reviewed-by: Eike Rathke <erack@redhat.com>
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>

Do not gather function data over and over again for each formula input

The function list changes only if switched to/from English
function names or if reset for AddIn config and only then needs to
be rebuilt. In all other cases simply reuse a once obtained data
set and only append the dynamic document content.

Change-Id: I5b1d14205e2933010a1b4382c985594d75802742
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138890
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>

Move input handler function names to ScGlobal static

... as there is only one function list and
InputHandlerFunctionNames can be shared instead of each
ScInputHandler holding their own copy.

Change-Id: Id82b2020f8846456ce7464daa83feb6915792aa2
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139012
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>

Use ScFunctionList::IsEnglishFunctionNames()

Change-Id: I21a7bf18c2117187b2e8c770b9367f46323b2c2d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139054
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>

Make static ScCompiler::GetCharClassLocalized() public as well

... and mutex guard it.

Change-Id: Ief9c6deaf7974ac43c7ae439a0fb73c29eced283
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138733
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139443
diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx
index cb60e1f..b7896c2 100644
--- a/sc/inc/compiler.hxx
+++ b/sc/inc/compiler.hxx
@@ -378,8 +378,8 @@ private:

    bool HasPossibleNamedRangeConflict(SCTAB nTab) const;

    static const CharClass* GetCharClassLocalized();
public:
    static const CharClass* GetCharClassLocalized();
    static const CharClass* GetCharClassEnglish();

public:
diff --git a/sc/inc/funcdesc.hxx b/sc/inc/funcdesc.hxx
index 0f37e92..0182941 100644
--- a/sc/inc/funcdesc.hxx
+++ b/sc/inc/funcdesc.hxx
@@ -253,9 +253,12 @@ public:

    const ScFuncDesc* GetFunction( sal_uInt32 nIndex ) const;

    bool IsEnglishFunctionNames() const { return mbEnglishFunctionNames; }

private:
    ::std::vector<const ScFuncDesc*> aFunctionList; /**< List of functions */
    ::std::vector<const ScFuncDesc*>::iterator aFunctionListIter; /**< position in function list */
    bool mbEnglishFunctionNames;
};

/**
diff --git a/sc/inc/global.hxx b/sc/inc/global.hxx
index 47b93c8..6c43f03 100644
--- a/sc/inc/global.hxx
+++ b/sc/inc/global.hxx
@@ -20,6 +20,7 @@
#pragma once

#include "address.hxx"
#include "typedstrdata.hxx"
#include <i18nlangtag/lang.h>
#include <svx/svdtypes.hxx>
#include <tools/ref.hxx>
@@ -455,6 +456,17 @@ struct ScImportParam
    bool            operator==  ( const ScImportParam& r ) const;
};

// Formula data replacement character for a pair of parentheses at end of
// function name, to force sorting parentheses before all other characters.
// Collation may treat parentheses differently.
constexpr sal_Unicode cParenthesesReplacement = 0x0001;
struct InputHandlerFunctionNames
{
    ScTypedCaseStrSet       maFunctionData;
    ScTypedCaseStrSet       maFunctionDataPara;
    std::set<sal_Unicode>   maFunctionChar;
};

class ScDocShell;
class SvxSearchItem;
class ScAutoFormat;
@@ -523,6 +535,8 @@ class ScGlobal

    static std::atomic<sc::SharedStringPoolPurge*> pSharedStringPoolPurge;

    static InputHandlerFunctionNames maInputHandlerFunctionNames;

    static void                 InitPPT();

public:
@@ -595,6 +609,7 @@ public:
    static ScFunctionList*  GetStarCalcFunctionList();
    static ScFunctionMgr*   GetStarCalcFunctionMgr();
    static void             ResetFunctionList();
    static const InputHandlerFunctionNames& GetInputHandlerFunctionNames();

    static OUString         GetErrorString(FormulaError nErrNumber);
    static OUString         GetLongErrorString(FormulaError nErrNumber);
diff --git a/sc/source/core/data/funcdesc.cxx b/sc/source/core/data/funcdesc.cxx
index c8045e6..1fa47a5 100644
--- a/sc/source/core/data/funcdesc.cxx
+++ b/sc/source/core/data/funcdesc.cxx
@@ -398,6 +398,7 @@ bool ScFuncDesc::compareByName(const ScFuncDesc* a, const ScFuncDesc* b)
#define ENTRY(CODE) CODE, SAL_N_ELEMENTS(CODE)

ScFunctionList::ScFunctionList( bool bEnglishFunctionNames )
    : mbEnglishFunctionNames( bEnglishFunctionNames )
{
    sal_Int32  nMaxFuncNameLen = 0; // Length of longest function name

@@ -958,7 +959,7 @@ ScFunctionList::ScFunctionList( bool bEnglishFunctionNames )
        pDesc = new ScFuncDesc;
        pDesc->nFIndex = nNextId++;

        if ( pUnoAddIns->FillFunctionDesc( nFunc, *pDesc, bEnglishFunctionNames ) )
        if ( pUnoAddIns->FillFunctionDesc( nFunc, *pDesc, mbEnglishFunctionNames ) )
        {
            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 46277a8..a7b63ce 100644
--- a/sc/source/core/data/global.cxx
+++ b/sc/source/core/data/global.cxx
@@ -119,6 +119,9 @@ sal_uInt16 nScFillModeMouseModifier = 0; //FIXME: And this

bool ScGlobal::bThreadedGroupCalcInProgress = false;

InputHandlerFunctionNames ScGlobal::maInputHandlerFunctionNames;


// Static functions

bool ScGlobal::HasAttrChanged( const SfxItemSet&  rNewAttrs,
@@ -641,6 +644,40 @@ void ScGlobal::ResetFunctionList()
    // FunctionMgr has pointers into FunctionList, must also be updated
    xStarCalcFunctionMgr.reset();
    xStarCalcFunctionList.reset();
    // Building new names also needs InputHandler data to be refreshed.
    maInputHandlerFunctionNames = InputHandlerFunctionNames();
}

const InputHandlerFunctionNames& ScGlobal::GetInputHandlerFunctionNames()
{
    if (maInputHandlerFunctionNames.maFunctionData.empty())
    {
        const OUString aParenthesesReplacement( cParenthesesReplacement);
        const ScFunctionList* pFuncList = GetStarCalcFunctionList();
        const sal_uInt32 nListCount = pFuncList->GetCount();
        const CharClass* pCharClass = (pFuncList->IsEnglishFunctionNames()
                ? ScCompiler::GetCharClassEnglish()
                : ScCompiler::GetCharClassLocalized());
        for (sal_uInt32 i=0; i < nListCount; ++i)
        {
            const ScFuncDesc* pDesc = pFuncList->GetFunction( i );
            if ( pDesc->mxFuncName )
            {
                OUString aFuncName(pCharClass->uppercase(*(pDesc->mxFuncName)));
                // fdo#75264 fill maFormulaChar with all characters used in formula names
                for (sal_Int32 j = 0; j < aFuncName.getLength(); j++)
                    maInputHandlerFunctionNames.maFunctionChar.insert(aFuncName[j]);
                maInputHandlerFunctionNames.maFunctionData.insert(
                        ScTypedStrData(*(pDesc->mxFuncName) + aParenthesesReplacement, 0.0, 0.0,
                            ScTypedStrData::Standard));
                pDesc->initArgumentInfo();
                OUString aEntry = pDesc->getSignature();
                maInputHandlerFunctionNames.maFunctionDataPara.insert(
                        ScTypedStrData(aEntry, 0.0, 0.0, ScTypedStrData::Standard));
            }
        }
    }
    return maInputHandlerFunctionNames;
}

ScUnitConverter* ScGlobal::GetUnitConverter()
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 580c7ef..7bcb949 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -242,8 +242,12 @@ const CharClass* ScCompiler::GetCharClassLocalized()
    {
        // Switching UI language requires restart; if not, we would have to
        // keep track of that.
        pCharClassLocalized = new CharClass(
                ::comphelper::getProcessComponentContext(), Application::GetSettings().GetUILanguageTag());
        osl::MutexGuard aGuard(maMutex);
        if (!pCharClassLocalized)
        {
            pCharClassLocalized = new CharClass( ::comphelper::getProcessComponentContext(),
                    Application::GetSettings().GetUILanguageTag());
        }
    }
    return pCharClassLocalized;
}
diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx
index 9ad38d7..b837cb2 100644
--- a/sc/source/ui/app/inputhdl.cxx
+++ b/sc/source/ui/app/inputhdl.cxx
@@ -67,6 +67,7 @@
#include <tabvwsh.hxx>
#include <docsh.hxx>
#include <scmod.hxx>
#include <formulaopt.hxx>
#include <uiitems.hxx>
#include <global.hxx>
#include <sc.hrc>
@@ -99,11 +100,6 @@ using namespace formula;

namespace {

// Formula data replacement character for a pair of parentheses at end of
// function name, to force sorting parentheses before all other characters.
// Collation may treat parentheses differently.
const sal_Unicode cParenthesesReplacement = 0x0001;

ScTypedCaseStrSet::const_iterator findText(
    const ScTypedCaseStrSet& rDataSet, ScTypedCaseStrSet::const_iterator const & itPos,
    const OUString& rStart, OUString& rResult, bool bBack)
@@ -1020,27 +1016,11 @@ void ScInputHandler::GetFormulaData()

    const OUString aParenthesesReplacement( cParenthesesReplacement);
    const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList();
    sal_uInt32 nListCount = pFuncList->GetCount();
    for(sal_uInt32 i=0;i<nListCount;i++)
    {
        const ScFuncDesc* pDesc = pFuncList->GetFunction( i );
        if ( pDesc->mxFuncName )
        {
            const sal_Unicode* pName = pDesc->mxFuncName->getStr();
            const sal_Int32 nLen = pDesc->mxFuncName->getLength();
            // fdo#75264 fill maFormulaChar with all characters used in formula names
            for ( sal_Int32 j = 0; j < nLen; j++ )
            {
                sal_Unicode c = pName[ j ];
                maFormulaChar.insert( c );
            }
            OUString aFuncName = *pDesc->mxFuncName + aParenthesesReplacement;
            pFormulaData->insert(ScTypedStrData(aFuncName, 0.0, 0.0, ScTypedStrData::Standard));
            pDesc->initArgumentInfo();
            OUString aEntry = pDesc->getSignature();
            pFormulaDataPara->insert(ScTypedStrData(aEntry, 0.0, 0.0, ScTypedStrData::Standard));
        }
    }
    const sal_uInt32 nListCount = pFuncList->GetCount();
    const InputHandlerFunctionNames& rFunctionNames = ScGlobal::GetInputHandlerFunctionNames();
    *pFormulaData     = rFunctionNames.maFunctionData;
    *pFormulaDataPara = rFunctionNames.maFunctionDataPara;
    maFormulaChar     = rFunctionNames.maFunctionChar;

    // Increase suggestion priority of MRU formulas
    const ScAppOptions& rOpt = SC_MOD()->GetAppOptions();
@@ -1065,8 +1045,19 @@ void ScInputHandler::GetFormulaData()
        }
    }
    miAutoPosFormula = pFormulaData->end();
    rDoc.GetFormulaEntries( *pFormulaData );
    rDoc.GetFormulaEntries( *pFormulaDataPara );

    // tdf#142031 - collect all the characters for the formula suggestion auto input
    ScTypedCaseStrSet aStrSet;
    rDoc.GetFormulaEntries( aStrSet );
    for (auto iter = aStrSet.begin(); iter != aStrSet.end(); ++iter)
    {
        const OUString aFuncName = ScGlobal::getCharClass().uppercase((*iter).GetString());
        // fdo#75264 fill maFormulaChar with all characters used in formula names
        for (sal_Int32 j = 0; j < aFuncName.getLength(); j++)
            maFormulaChar.insert(aFuncName[j]);
    }
    pFormulaData->insert(aStrSet.begin(), aStrSet.end());
    pFormulaDataPara->insert(aStrSet.begin(), aStrSet.end());
}

IMPL_LINK( ScInputHandler, ShowHideTipVisibleParentListener, VclWindowEvent&, rEvent, void )
diff --git a/sc/source/ui/inc/inputhdl.hxx b/sc/source/ui/inc/inputhdl.hxx
index 765c325..ca70287 100644
--- a/sc/source/ui/inc/inputhdl.hxx
+++ b/sc/source/ui/inc/inputhdl.hxx
@@ -66,8 +66,9 @@ private:
    std::unique_ptr<ScTypedCaseStrSet> pColumnData;
    std::unique_ptr<ScTypedCaseStrSet> pFormulaData;
    std::unique_ptr<ScTypedCaseStrSet> pFormulaDataPara;
    ScTypedCaseStrSet::const_iterator miAutoPosColumn;
    ScTypedCaseStrSet::const_iterator miAutoPosFormula;
    ScTypedCaseStrSet::const_iterator  miAutoPosColumn;
    ScTypedCaseStrSet::const_iterator  miAutoPosFormula;
    std::set<sal_Unicode>              maFormulaChar;

    VclPtr<vcl::Window>     pTipVisibleParent;
    void*                   nTipVisible;
@@ -127,8 +128,6 @@ private:
    std::unique_ptr<ScRangeFindList>
                            pRangeFindList;

    ::std::set< sal_Unicode >    maFormulaChar;  //fdo 75264

private:
    void            UpdateActiveView();
    void            SyncViews( const EditView* pSourceView = nullptr );