tdf#124513 Allow to use multiple Formula dialog instances

Reviewed-on: https://gerrit.libreoffice.org/79463
Tested-by: Jenkins
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
(cherry picked from commit b3a9fd1c51b4d0c2a8146c250e5571cc38eae9e6)

Change-Id: Ia24556f40dd06e3acb40f24334ab972e2dada26a
Reviewed-on: https://gerrit.libreoffice.org/83702
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/sc/inc/scmod.hxx b/sc/inc/scmod.hxx
index 7d0d7e0..6f42d44 100644
--- a/sc/inc/scmod.hxx
+++ b/sc/inc/scmod.hxx
@@ -100,7 +100,6 @@ class SAL_DLLPUBLIC_RTTI ScModule: public SfxModule, public SfxListener, public 
    std::unique_ptr<SvtCTLOptions>           m_pCTLOptions;
    std::unique_ptr<SvtUserOptions>          m_pUserOptions;
    std::unique_ptr<SfxErrorHandler>  m_pErrorHdl;
    std::unique_ptr<ScFormEditData>   m_pFormEditData;
    sal_uInt16          m_nCurRefDlgId;
    bool                m_bIsWaterCan:1;
    bool                m_bIsInEditCommand:1;
@@ -206,7 +205,6 @@ public:
    void                InputSelection( const EditView* pView );
    void                InputChanged( const EditView* pView );
    ScInputHandler*     GetInputHdl( ScTabViewShell* pViewSh = nullptr, bool bUseRef = true );

    void                SetRefInputHdl( ScInputHandler* pNew );
    ScInputHandler*     GetRefInputHdl() { return m_pRefInputHandler;}

@@ -217,14 +215,9 @@ public:
    void                InputSetSelection( sal_Int32 nStart, sal_Int32 nEnd );
    void                InputReplaceSelection( const OUString& rStr );
    void                InputTurnOffWinEngine();
    OUString            InputGetFormulaStr();
    void                ActivateInputWindow( const OUString* pStr = nullptr,
                                                bool bMatrix = false );

    void                InitFormEditData();
    void                ClearFormEditData();
    ScFormEditData*     GetFormEditData()       { return m_pFormEditData.get(); }

    // input of reference:
    SC_DLLPUBLIC void   SetRefDialog( sal_uInt16 nId, bool bVis, SfxViewFrame* pViewFrm = nullptr );
    bool                IsModalMode(SfxObjectShell* pDocSh = nullptr);
diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx
index ecbdfaf..1988d7b 100644
--- a/sc/source/ui/app/inputhdl.cxx
+++ b/sc/source/ui/app/inputhdl.cxx
@@ -3639,9 +3639,12 @@ void ScInputHandler::NotifyChange( const ScInputHdlState* pState,
    {
        ScModule* pScMod = SC_MOD();

        ScTabViewShell* pScTabViewShell = pScMod ? dynamic_cast<ScTabViewShell*>(pScMod->GetViewShell()) : nullptr;

        // Also take foreign reference input into account here (e.g. FunctionsAutoPilot),
        // FormEditData, if we're switching from Help to Calc:
        if ( !bFormulaMode && !pScMod->IsFormulaMode() && !pScMod->GetFormEditData() )
        if ( !bFormulaMode && !pScMod->IsFormulaMode() &&
             ( !pScTabViewShell || !pScTabViewShell->GetFormEditData() ) )
        {
            bool bIgnore = false;
            if ( bModified )
diff --git a/sc/source/ui/app/inputwin.cxx b/sc/source/ui/app/inputwin.cxx
index 216a5bd..dc5f92c 100644
--- a/sc/source/ui/app/inputwin.cxx
+++ b/sc/source/ui/app/inputwin.cxx
@@ -66,6 +66,7 @@
#include <editeng/fontitem.hxx>
#include <AccessibleEditObject.hxx>
#include <AccessibleText.hxx>
#include <comphelper/lok.hxx>
#include <comphelper/string.hxx>
#include <com/sun/star/frame/XLayoutManager.hpp>
#include <helpids.h>
@@ -309,7 +310,7 @@ void ScInputWindow::Select()
            {
                //! new method at ScModule to query if function autopilot is open
                SfxViewFrame* pViewFrm = SfxViewFrame::Current();
                if ( pViewFrm && !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) )
                if ( pViewFrm && ( comphelper::LibreOfficeKit::isActive() || !pViewFrm->GetChildWindow( SID_OPENDLG_FUNCTION ) ) )
                {
                    pViewFrm->GetDispatcher()->Execute( SID_OPENDLG_FUNCTION,
                                              SfxCallMode::SYNCHRON | SfxCallMode::RECORD );
diff --git a/sc/source/ui/app/scmod.cxx b/sc/source/ui/app/scmod.cxx
index 76faf34..8bf1555 100644
--- a/sc/source/ui/app/scmod.cxx
+++ b/sc/source/ui/app/scmod.cxx
@@ -166,8 +166,6 @@ ScModule::~ScModule()

    SfxItemPool::Free(m_pMessagePool);

    m_pFormEditData.reset();

    m_pDragData.reset();
    m_pErrorHdl.reset();

@@ -654,16 +652,6 @@ void ScModule::SetSelectionTransfer( ScSelectionTransferObj* pNew )
    m_pSelTransfer = pNew;
}

void ScModule::InitFormEditData()
{
    m_pFormEditData.reset( new ScFormEditData );
}

void ScModule::ClearFormEditData()
{
    m_pFormEditData.reset();
}

void ScModule::SetViewOptions( const ScViewOptions& rOpt )
{
    if ( !m_pViewCfg )
@@ -1318,7 +1306,7 @@ void ScModule::ModifyOptions( const SfxItemSet& rOptSet )
 */
ScInputHandler* ScModule::GetInputHdl( ScTabViewShell* pViewSh, bool bUseRef )
{
    if ( m_pRefInputHandler && bUseRef )
    if ( !comphelper::LibreOfficeKit::isActive() && m_pRefInputHandler && bUseRef )
        return m_pRefInputHandler;

    ScInputHandler* pHdl = nullptr;
@@ -1443,15 +1431,6 @@ void ScModule::InputTurnOffWinEngine()
        pHdl->InputTurnOffWinEngine();
}

OUString ScModule::InputGetFormulaStr()
{
    ScInputHandler* pHdl = GetInputHdl();
    OUString aStr;
    if ( pHdl )
        aStr = pHdl->GetFormString();
    return aStr;
}

void ScModule::ActivateInputWindow( const OUString* pStrFormula, bool bMatrix )
{
    ScInputHandler* pHdl = GetInputHdl();
@@ -1493,7 +1472,8 @@ void ScModule::SetRefDialog( sal_uInt16 nId, bool bVis, SfxViewFrame* pViewFrm )
{
    //TODO: Move reference dialog handling to view
    //      Just keep function autopilot here for references to other documents
    if(m_nCurRefDlgId==0 || (nId==m_nCurRefDlgId && !bVis))
    if ( m_nCurRefDlgId == 0 || ( nId == m_nCurRefDlgId && !bVis )
       || ( comphelper::LibreOfficeKit::isActive() && m_nCurRefDlgId == SID_OPENDLG_FUNCTION ) )
    {
        if ( !pViewFrm )
            pViewFrm = SfxViewFrame::Current();
@@ -1661,7 +1641,13 @@ bool ScModule::IsFormulaMode()

    if ( m_nCurRefDlgId )
    {
        SfxChildWindow* pChildWnd = lcl_GetChildWinFromCurrentView( m_nCurRefDlgId );
        SfxChildWindow* pChildWnd = nullptr;

        if ( comphelper::LibreOfficeKit::isActive() )
            pChildWnd = lcl_GetChildWinFromCurrentView( m_nCurRefDlgId );
        else
            pChildWnd = lcl_GetChildWinFromAnyView( m_nCurRefDlgId );

        if ( pChildWnd )
        {
            if (pChildWnd->GetWindow())
diff --git a/sc/source/ui/formdlg/formula.cxx b/sc/source/ui/formdlg/formula.cxx
index 3c412a9..56c406e 100644
--- a/sc/source/ui/formdlg/formula.cxx
+++ b/sc/source/ui/formdlg/formula.cxx
@@ -60,11 +60,12 @@ ScFormulaDlg::ScFormulaDlg(SfxBindings* pB, SfxChildWindow* pCW,
                           weld::Window* pParent, const ScViewData* pViewData, const formula::IFunctionManager* _pFunctionMgr)
    : formula::FormulaDlg(pB, pCW, pParent, _pFunctionMgr, this)
    , m_aHelper(this,pB)
    , m_pViewShell( nullptr )
{
    m_aHelper.SetDialog(m_xDialog.get());
    ScModule* pScMod = SC_MOD();
    pScMod->InputEnterHandler();
    ScTabViewShell* pScViewShell = nullptr;
    m_pViewShell = nullptr;

    // title has to be from the view that opened the dialog,
    // even if it's not the current view
@@ -77,9 +78,9 @@ ScFormulaDlg::ScFormulaDlg(SfxBindings* pB, SfxChildWindow* pCW,
            SfxViewFrame* pMyViewFrm = pMyDisp->GetFrame();
            if (pMyViewFrm)
            {
                pScViewShell = dynamic_cast<ScTabViewShell*>( pMyViewFrm->GetViewShell()  );
                if( pScViewShell )
                    pScViewShell->UpdateInputHandler(true);
                m_pViewShell = dynamic_cast<ScTabViewShell*>( pMyViewFrm->GetViewShell()  );
                if( m_pViewShell )
                    m_pViewShell->UpdateInputHandler(true);
            }
        }
    }
@@ -93,12 +94,11 @@ ScFormulaDlg::ScFormulaDlg(SfxBindings* pB, SfxChildWindow* pCW,
    m_xOpCodeMapper.set(ScServiceProvider::MakeInstance(ScServiceProvider::Type::OPCODEMAPPER,
                                                        static_cast<ScDocShell*>(m_pDoc->GetDocumentShell())),uno::UNO_QUERY);

    ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl(pScViewShell);
    ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl(m_pViewShell);

    OSL_ENSURE( pInputHdl, "Missing input handler :-/" );
    assert(pInputHdl && "Missing input handler :-/");

    if ( pInputHdl )
        pInputHdl->NotifyChange( nullptr );
    pInputHdl->NotifyChange( nullptr );

    ScFormulaReferenceHelper::enableInput( true );
    ScFormulaReferenceHelper::EnableSpreadsheets();
@@ -108,10 +108,10 @@ ScFormulaDlg::ScFormulaDlg(SfxBindings* pB, SfxChildWindow* pCW,
    notifyChange();
    fill();

    ScFormEditData* pData = pScMod->GetFormEditData();
    ScFormEditData* pData = m_pViewShell->GetFormEditData();
    if (!pData)
    {
        pScMod->SetRefInputHdl(pScMod->GetInputHdl());
        pScMod->SetRefInputHdl(pInputHdl);

        m_pDoc = pViewData->GetDocument();
        SCCOL nCol = pViewData->GetCurX();
@@ -119,9 +119,9 @@ ScFormulaDlg::ScFormulaDlg(SfxBindings* pB, SfxChildWindow* pCW,
        SCTAB nTab = pViewData->GetTabNo();
        m_CursorPos = ScAddress( nCol, nRow, nTab );

        pScMod->InitFormEditData();                             // create new
        pData = pScMod->GetFormEditData();
        pData->SetInputHandler(pScMod->GetInputHdl());
        m_pViewShell->InitFormEditData();                             // create new
        pData = m_pViewShell->GetFormEditData();
        pData->SetInputHandler(pInputHdl);
        pData->SetDocShell(pViewData->GetDocShell());

        OSL_ENSURE(pData,"FormEditData not available");
@@ -142,12 +142,12 @@ ScFormulaDlg::ScFormulaDlg(SfxBindings* pB, SfxChildWindow* pCW,
            sal_Int32 nFEnd   = 0;
            if ( GetFormulaHelper().GetNextFunc( aFormula, false, nFStart, &nFEnd) )
            {
                pScMod->InputReplaceSelection( aFormula );
                pScMod->InputSetSelection( nFStart, nFEnd );
                pInputHdl->InputReplaceSelection( aFormula );
                pInputHdl->InputSetSelection( nFStart, nFEnd );
                sal_Int32 PrivStart, PrivEnd;
                pScMod->InputGetSelection( PrivStart, PrivEnd);
                pInputHdl->InputGetSelection( PrivStart, PrivEnd);

                eMode = SetMeText(pScMod->InputGetFormulaStr(),PrivStart, PrivEnd, bMatrix, true, true);
                eMode = SetMeText(pInputHdl->GetFormString(),PrivStart, PrivEnd, bMatrix, true, true);
                pData->SetFStart( nFStart );
            }
            else
@@ -160,11 +160,11 @@ ScFormulaDlg::ScFormulaDlg(SfxBindings* pB, SfxChildWindow* pCW,
            if ( aFormula.startsWith("=") )
                aNewFormula = aFormula;

            pScMod->InputReplaceSelection( aNewFormula );
            pScMod->InputSetSelection( 1, aNewFormula.getLength()+1 );
            pInputHdl->InputReplaceSelection( aNewFormula );
            pInputHdl->InputSetSelection( 1, aNewFormula.getLength()+1 );
            sal_Int32 PrivStart, PrivEnd;
            pScMod->InputGetSelection( PrivStart, PrivEnd);
            SetMeText(pScMod->InputGetFormulaStr(),PrivStart, PrivEnd,bMatrix,false,false);
            pInputHdl->InputGetSelection( PrivStart, PrivEnd);
            SetMeText(pInputHdl->GetFormString(),PrivStart, PrivEnd,bMatrix,false,false);

            pData->SetFStart( 1 );      // after "="
        }
@@ -179,9 +179,7 @@ ScFormulaDlg::ScFormulaDlg(SfxBindings* pB, SfxChildWindow* pCW,

void ScFormulaDlg::notifyChange()
{
    ScModule* pScMod = SC_MOD();

    ScInputHandler* pInputHdl = pScMod->GetInputHdl();
    ScInputHandler* pInputHdl = m_pViewShell->GetInputHandler();
    if ( pInputHdl )
        pInputHdl->NotifyChange( nullptr );
}
@@ -189,7 +187,7 @@ void ScFormulaDlg::notifyChange()
void ScFormulaDlg::fill()
{
    ScModule* pScMod = SC_MOD();
    ScFormEditData* pData = pScMod->GetFormEditData();
    ScFormEditData* pData = static_cast<ScFormEditData*>(getFormEditData());
    notifyChange();
    OUString rStrExp;
    if (pData)
@@ -219,11 +217,11 @@ void ScFormulaDlg::fill()
            pData->SetInputHandler(pInputHdl);
        }

        OUString aOldFormulaTmp(pScMod->InputGetFormulaStr());
        pScMod->InputSetSelection( 0, aOldFormulaTmp.getLength());
        OUString aOldFormulaTmp(pData->GetInputHandler()->GetFormString());
        pData->GetInputHandler()->InputSetSelection( 0, aOldFormulaTmp.getLength());

        rStrExp=pData->GetUndoStr();
        pScMod->InputReplaceSelection(rStrExp);
        pData->GetInputHandler()->InputReplaceSelection(rStrExp);

        SetMeText(rStrExp);

@@ -235,16 +233,18 @@ void ScFormulaDlg::fill()

ScFormulaDlg::~ScFormulaDlg()
{
    ScModule* pScMod = SC_MOD();
    ScFormEditData* pData = pScMod->GetFormEditData();
    ScFormEditData* pData = m_pViewShell->GetFormEditData();

    m_aHelper.dispose();

    if (pData) // close doesn't destroy;
    {
        //set back reference input handler
        pScMod->SetRefInputHdl(nullptr);
        SC_MOD()->SetRefInputHdl(nullptr);
        StoreFormEditData(pData);
    }

    m_pViewShell->ClearFormEditData();
}

bool ScFormulaDlg::IsInputHdl(const ScInputHandler* pHdl)
@@ -556,8 +556,8 @@ void ScFormulaDlg::setDispatcherLock( bool bLock )
}
void ScFormulaDlg::deleteFormData()
{
    ScModule* pScMod = SC_MOD();
    pScMod->ClearFormEditData();        // pData is invalid!
    if (m_pViewShell)
        m_pViewShell->ClearFormEditData();        // pData is invalid!
}
void ScFormulaDlg::clear()
{
@@ -574,10 +574,9 @@ void ScFormulaDlg::clear()
}
void ScFormulaDlg::switchBack()
{
    ScModule* pScMod = SC_MOD();
    // back to the document
    // (foreign doc could be above - #34222#)
    ScInputHandler* pHdl = pScMod->GetInputHdl();
    ScInputHandler* pHdl = m_pViewShell->GetInputHandler();
    if ( pHdl )
    {
        pHdl->ViewShellGone(nullptr);  // -> get active view
@@ -602,8 +601,10 @@ void ScFormulaDlg::switchBack()
}
formula::FormEditData* ScFormulaDlg::getFormEditData() const
{
    ScModule* pScMod = SC_MOD();
    return pScMod->GetFormEditData();
    ScTabViewShell* pViewShell = m_pViewShell;
    if (pViewShell)
        return pViewShell->GetFormEditData();
    return nullptr;
}
void ScFormulaDlg::setCurrentFormula(const OUString& _sReplacement)
{
@@ -639,8 +640,10 @@ void ScFormulaDlg::getSelection(sal_Int32& _nStart, sal_Int32& _nEnd) const
}
OUString ScFormulaDlg::getCurrentFormula() const
{
    ScModule* pScMod = SC_MOD();
    return pScMod->InputGetFormulaStr();
    ScFormEditData* pData = m_pViewShell->GetFormEditData();
    if (pData && pData->GetInputHandler())
        return pData->GetInputHandler()->GetFormString();
    return "";
}
formula::IFunctionManager* ScFormulaDlg::getFunctionManager()
{
diff --git a/sc/source/ui/inc/formula.hxx b/sc/source/ui/inc/formula.hxx
index 9d4e7c6..5b19928 100644
--- a/sc/source/ui/inc/formula.hxx
+++ b/sc/source/ui/inc/formula.hxx
@@ -41,6 +41,7 @@ class ScFormulaDlg final : public formula::FormulaDlg,

            ScDocument*                 m_pDoc;
            ScAddress                   m_CursorPos;
            ScTabViewShell*             m_pViewShell;
    mutable std::shared_ptr<ScCompiler> m_xCompiler;

public:
diff --git a/sc/source/ui/inc/tabvwsh.hxx b/sc/source/ui/inc/tabvwsh.hxx
index 7d51dbc..f947250 100644
--- a/sc/source/ui/inc/tabvwsh.hxx
+++ b/sc/source/ui/inc/tabvwsh.hxx
@@ -88,6 +88,7 @@ enum ObjectSelectionType
    OST_Media
};

class ScFormEditData;
class SC_DLLPUBLIC ScTabViewShell: public SfxViewShell, public ScDBFunc
{
private:
@@ -112,6 +113,7 @@ private:

    std::unique_ptr<FmFormShell> pFormShell;

    std::unique_ptr<ScFormEditData> mpFormEditData;
    std::unique_ptr<ScInputHandler, o3tl::default_delete<ScInputHandler>> mpInputHandler;              // for OLE input cell

    std::unique_ptr<::editeng::SvxBorderLine> pCurFrameLine;
@@ -162,7 +164,6 @@ private:
    bool    mbInSwitch;
    OUString   maName;
    OUString   maScope;

private:
    void    Construct( TriState nForceDesignMode );

@@ -391,6 +392,10 @@ public:
    static bool isAnyEditViewInRange(bool bColumns, SCCOLROW nStart, SCCOLROW nEnd);
    css::uno::Reference<css::drawing::XShapes> getSelectedXShapes();
    static  css::uno::Reference<css::datatransfer::XTransferable2> GetClipData(vcl::Window* pWin);

    void InitFormEditData();
    void ClearFormEditData();
    ScFormEditData* GetFormEditData() { return mpFormEditData.get(); }
};

#endif
diff --git a/sc/source/ui/view/cellsh3.cxx b/sc/source/ui/view/cellsh3.cxx
index 621427d..0d380e1 100644
--- a/sc/source/ui/view/cellsh3.cxx
+++ b/sc/source/ui/view/cellsh3.cxx
@@ -46,6 +46,7 @@
#include <markdata.hxx>
#include <scabstdlg.hxx>
#include <columnspanset.hxx>
#include <comphelper/lok.hxx>

#include <memory>

@@ -308,8 +309,8 @@ void ScCellShell::Execute( SfxRequest& rReq )
                sal_uInt16 nId = SID_OPENDLG_FUNCTION;
                SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame();
                SfxChildWindow* pWnd = pViewFrm->GetChildWindow( nId );

                pScMod->SetRefDialog( nId, pWnd == nullptr );
                bool bVis = comphelper::LibreOfficeKit::isActive() || pWnd == nullptr;
                pScMod->SetRefDialog( nId, bVis );
                rReq.Ignore();
            }
            break;
diff --git a/sc/source/ui/view/tabvwsh4.cxx b/sc/source/ui/view/tabvwsh4.cxx
index 46259a8f..656f57b 100644
--- a/sc/source/ui/view/tabvwsh4.cxx
+++ b/sc/source/ui/view/tabvwsh4.cxx
@@ -21,6 +21,7 @@

#include <scitems.hxx>
#include <editeng/eeitem.hxx>
#include <formdata.hxx>

#include <sfx2/app.hxx>
#include <svx/dialogs.hrc>
@@ -1777,6 +1778,7 @@ ScTabViewShell::~ScTabViewShell()
    pPivotShell.reset();
    pAuditingShell.reset();
    pCurFrameLine.reset();
    mpFormEditData.reset();
    mpInputHandler.reset();
    pPivotSource.reset();
    pDialogDPObject.reset();
diff --git a/sc/source/ui/view/tabvwsha.cxx b/sc/source/ui/view/tabvwsha.cxx
index fbd9ca9..acee56fe 100644
--- a/sc/source/ui/view/tabvwsha.cxx
+++ b/sc/source/ui/view/tabvwsha.cxx
@@ -740,7 +740,7 @@ void ScTabViewShell::ExecuteSave( SfxRequest& rReq )
            // we will save the doc immediately afterwards, the modified state event
            // is clobbered. To avoid that, we notify all views immediately of the
            // modified state, apply the modification, then save the document.
            ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
            ScInputHandler* pHdl = GetInputHandler();
            if (pHdl != nullptr && pHdl->GetModified())
                SfxLokHelper::notifyAllViews(LOK_CALLBACK_STATE_CHANGED, ".uno:ModifiedStatus=true");
        }
diff --git a/sc/source/ui/view/tabvwshc.cxx b/sc/source/ui/view/tabvwshc.cxx
index 939a722..640309b 100644
--- a/sc/source/ui/view/tabvwshc.cxx
+++ b/sc/source/ui/view/tabvwshc.cxx
@@ -59,6 +59,7 @@
#include <condformatdlg.hxx>
#include <xmlsourcedlg.hxx>
#include <condformatdlgitem.hxx>
#include <formdata.hxx>

#include <RandomNumberGeneratorDialog.hxx>
#include <SamplingDialog.hxx>
@@ -677,4 +678,14 @@ const OUString ScTabViewShell::DoAutoSum(bool& rRangeFinder, bool& rSubTotal, co
    return aFormula;
}

void ScTabViewShell::InitFormEditData()
{
    mpFormEditData.reset(new ScFormEditData);
}

void ScTabViewShell::ClearFormEditData()
{
    mpFormEditData.reset();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */