Related: tdf#137577 Be able to select a global named range from Name Box

... if an identical sheet-local name exists.

Change-Id: I6d92a7ed93e81da64f60c26fd81eb6775582b053
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113384
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
diff --git a/sc/inc/rangeutl.hxx b/sc/inc/rangeutl.hxx
index aca68c6..2f4a9887 100644
--- a/sc/inc/rangeutl.hxx
+++ b/sc/inc/rangeutl.hxx
@@ -32,7 +32,14 @@
class ScDocument;
class ScRangeList;

enum RutlNameScope { RUTL_NONE=0, RUTL_NAMES, RUTL_DBASE };
enum RutlNameScope
{
    RUTL_NONE = 0,
    RUTL_NAMES,
    RUTL_NAMES_LOCAL,
    RUTL_NAMES_GLOBAL,
    RUTL_DBASE
};

class SC_DLLPUBLIC ScRangeUtil
{
diff --git a/sc/source/core/tool/rangeutl.cxx b/sc/source/core/tool/rangeutl.cxx
index 18473e0..a80db03 100644
--- a/sc/source/core/tool/rangeutl.cxx
+++ b/sc/source/core/tool/rangeutl.cxx
@@ -248,35 +248,43 @@
    SCROW nRowStart = 0;
    SCROW nRowEnd = 0;

    if( eScope==RUTL_NAMES )
    if (eScope == RUTL_NAMES || eScope == RUTL_NAMES_LOCAL || eScope == RUTL_NAMES_GLOBAL)
    {
        OUString aName(rName);
        SCTAB nTable = nCurTab;

        // First handle UI names like "local1 (Sheet1)", which point to a local
        // range name.
        const sal_Int32 nEndPos = aName.getLength() - 1;
        if (rName[nEndPos] == ')')
        if (eScope != RUTL_NAMES_GLOBAL)
        {
            const sal_Int32 nStartPos = aName.indexOf(" (");
            if (nStartPos != -1)
            // First handle UI names like "local1 (Sheet1)", which point to a
            // local range name.
            const sal_Int32 nEndPos = aName.getLength() - 1;
            if (rName[nEndPos] == ')')
            {
                OUString aSheetName = aName.copy(nStartPos+2, nEndPos-nStartPos-2);
                if (rDoc.GetTable(aSheetName, nTable))
                const sal_Int32 nStartPos = aName.indexOf(" (");
                if (nStartPos != -1)
                {
                    aName = aName.copy(0, nStartPos);
                    OUString aSheetName = aName.copy(nStartPos+2, nEndPos-nStartPos-2);
                    if (rDoc.GetTable(aSheetName, nTable))
                    {
                        aName = aName.copy(0, nStartPos);
                        eScope = RUTL_NAMES_LOCAL;
                    }
                    else
                        nTable = nCurTab;
                }
                else
                    nTable = nCurTab;
            }
        }
        // Then check for local range names.
        ScRangeName* pRangeNames = rDoc.GetRangeName( nTable );
        ScRangeData* pData = nullptr;

        aName = ScGlobal::getCharClassPtr()->uppercase(aName);
        if ( pRangeNames )
            pData = pRangeNames->findByUpperName(aName);
        if (!pData)
        ScRangeData* pData = nullptr;
        if (eScope != RUTL_NAMES_GLOBAL)
        {
            // Check for local range names.
            ScRangeName* pRangeNames = rDoc.GetRangeName( nTable );
            if ( pRangeNames )
                pData = pRangeNames->findByUpperName(aName);
        }
        if (!pData && eScope != RUTL_NAMES_LOCAL)
            pData = rDoc.GetRangeName()->findByUpperName(aName);
        if (pData)
        {
diff --git a/sc/source/ui/app/inputwin.cxx b/sc/source/ui/app/inputwin.cxx
index 3473ffc..2b5a48c 100644
--- a/sc/source/ui/app/inputwin.cxx
+++ b/sc/source/ui/app/inputwin.cxx
@@ -101,7 +101,8 @@
{
    SC_NAME_INPUT_CELL,
    SC_NAME_INPUT_RANGE,
    SC_NAME_INPUT_NAMEDRANGE,
    SC_NAME_INPUT_NAMEDRANGE_LOCAL,
    SC_NAME_INPUT_NAMEDRANGE_GLOBAL,
    SC_NAME_INPUT_DATABASE,
    SC_NAME_INPUT_ROW,
    SC_NAME_INPUT_SHEET,
@@ -2323,14 +2324,23 @@
        SCTAB nNameTab;
        sal_Int32 nNumeric;

        // From the context we know that when testing for a range name
        // sheet-local scope names have " (sheetname)" appended and global
        // names don't and can't contain ')', so we can force one or the other.
        const RutlNameScope eNameScope =
            ((!rText.isEmpty() && rText[rText.getLength()-1] == ')') ? RUTL_NAMES_LOCAL : RUTL_NAMES_GLOBAL);

        if (rText == ScResId(STR_MANAGE_NAMES))
            eRet = SC_MANAGE_NAMES;
        else if ( aRange.Parse( rText, rDoc, eConv ) & ScRefFlags::VALID )
            eRet = SC_NAME_INPUT_RANGE;
        else if ( aAddress.Parse( rText, rDoc, eConv ) & ScRefFlags::VALID )
            eRet = SC_NAME_INPUT_CELL;
        else if ( ScRangeUtil::MakeRangeFromName( rText, rDoc, nTab, aRange, RUTL_NAMES, eConv ) )
            eRet = SC_NAME_INPUT_NAMEDRANGE;
        else if ( ScRangeUtil::MakeRangeFromName( rText, rDoc, nTab, aRange, eNameScope, eConv ) )
        {
            eRet = ((eNameScope == RUTL_NAMES_LOCAL) ? SC_NAME_INPUT_NAMEDRANGE_LOCAL :
                    SC_NAME_INPUT_NAMEDRANGE_GLOBAL);
        }
        else if ( ScRangeUtil::MakeRangeFromName( rText, rDoc, nTab, aRange, RUTL_DBASE, eConv ) )
            eRet = SC_NAME_INPUT_DATABASE;
        else if ( comphelper::string::isdigitAsciiString( rText ) &&
@@ -2375,7 +2385,8 @@
            pStrId = STR_NAME_INPUT_CELL;
            break;
        case SC_NAME_INPUT_RANGE:
        case SC_NAME_INPUT_NAMEDRANGE:
        case SC_NAME_INPUT_NAMEDRANGE_LOCAL:
        case SC_NAME_INPUT_NAMEDRANGE_GLOBAL:
            pStrId = STR_NAME_INPUT_RANGE;      // named range or range reference
            break;
        case SC_NAME_INPUT_DATABASE:
@@ -2483,6 +2494,7 @@
                }
                else
                {
                    bool bForceGlobalName = false;
                    // for all selection types, execute the SID_CURRENTCELL slot.
                    if (eType == SC_NAME_INPUT_CELL || eType == SC_NAME_INPUT_RANGE)
                    {
@@ -2492,13 +2504,19 @@
                        aRange.ParseAny(aText, rDoc, rDoc.GetAddressConvention());
                        aText = aRange.Format(rDoc, ScRefFlags::RANGE_ABS_3D, ::formula::FormulaGrammar::CONV_OOO);
                    }
                    else if (eType == SC_NAME_INPUT_NAMEDRANGE_GLOBAL)
                    {
                        bForceGlobalName = true;
                    }

                    SfxStringItem aPosItem( SID_CURRENTCELL, aText );
                    SfxBoolItem aUnmarkItem( FN_PARAM_1, true );        // remove existing selection
                    // FN_PARAM_2 reserved for AlignToCursor
                    SfxBoolItem aForceGlobalName( FN_PARAM_3, bForceGlobalName );

                    pViewSh->GetViewData().GetDispatcher().ExecuteList( SID_CURRENTCELL,
                                        SfxCallMode::SYNCHRON | SfxCallMode::RECORD,
                                        { &aPosItem, &aUnmarkItem });
                                        { &aPosItem, &aUnmarkItem, &aForceGlobalName });
                }
            }
        }
diff --git a/sc/source/ui/view/tabvwsh3.cxx b/sc/source/ui/view/tabvwsh3.cxx
index e8fb0d8..7bbbd96 100644
--- a/sc/source/ui/view/tabvwsh3.cxx
+++ b/sc/source/ui/view/tabvwsh3.cxx
@@ -313,6 +313,10 @@
                if (pReqArgs->GetItemState(FN_PARAM_2, true, &pItem) == SfxItemState::SET)
                    bAlignToCursor = static_cast<const SfxBoolItem*>(pItem)->GetValue();

                bool bForceGlobalName = false;
                if (pReqArgs->GetItemState(FN_PARAM_3, true, &pItem) == SfxItemState::SET)
                    bForceGlobalName = static_cast<const SfxBoolItem*>(pItem)->GetValue();

                if ( nSlot == SID_JUMPTOMARK )
                {
                    //  URL has to be decoded for escaped characters (%20)
@@ -369,8 +373,9 @@
                // Is it a named area (first named ranges then database ranges)?
                else
                {
                    const RutlNameScope eScope = (bForceGlobalName ? RUTL_NAMES_GLOBAL : RUTL_NAMES);
                    formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();
                    if( ScRangeUtil::MakeRangeFromName( aAddress, rDoc, nTab, aScRange, RUTL_NAMES, eConv ) ||
                    if( ScRangeUtil::MakeRangeFromName( aAddress, rDoc, nTab, aScRange, eScope, eConv ) ||
                        ScRangeUtil::MakeRangeFromName( aAddress, rDoc, nTab, aScRange, RUTL_DBASE, eConv ) )
                    {
                        nResult |= ScRefFlags::VALID;