summaryrefslogtreecommitdiffstats
path: root/sc/source/ui/formdlg
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui/formdlg')
-rw-r--r--sc/source/ui/formdlg/dwfunctr.cxx410
-rw-r--r--sc/source/ui/formdlg/formdata.cxx33
-rw-r--r--sc/source/ui/formdlg/formula.cxx691
3 files changed, 1134 insertions, 0 deletions
diff --git a/sc/source/ui/formdlg/dwfunctr.cxx b/sc/source/ui/formdlg/dwfunctr.cxx
new file mode 100644
index 000000000..424c0ee99
--- /dev/null
+++ b/sc/source/ui/formdlg/dwfunctr.cxx
@@ -0,0 +1,410 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <comphelper/string.hxx>
+#include <editeng/editview.hxx>
+#include <sfx2/viewsh.hxx>
+#include <formula/funcvarargs.h>
+
+#include <global.hxx>
+#include <scmod.hxx>
+#include <inputhdl.hxx>
+#include <tabvwsh.hxx>
+#include <funcdesc.hxx>
+
+#include <dwfunctr.hxx>
+
+/*************************************************************************
+#* Member: ScFunctionWin
+#*------------------------------------------------------------------------
+#*
+#* Class: ScFunctionWin
+#*
+#* Function: Constructor of ScFunctionWin Class
+#*
+#* Input: Sfx - links, window, resource
+#*
+#* Output: ---
+#*
+#************************************************************************/
+
+ScFunctionWin::ScFunctionWin(weld::Widget* pParent)
+ : PanelLayout(pParent, "FunctionPanel", "modules/scalc/ui/functionpanel.ui")
+ , xCatBox(m_xBuilder->weld_combo_box("category"))
+ , xFuncList(m_xBuilder->weld_tree_view("funclist"))
+ , xInsertButton(m_xBuilder->weld_button("insert"))
+ , xFiFuncDesc(m_xBuilder->weld_label("funcdesc"))
+ , xConfigListener(new comphelper::ConfigurationListener("/org.openoffice.Office.Calc/Formula/Syntax"))
+ , xConfigChange(std::make_unique<EnglishFunctionNameChange>(xConfigListener, this))
+ , pFuncDesc(nullptr)
+{
+ xFuncList->set_size_request(-1, xFuncList->get_height_rows(10));
+
+ InitLRUList();
+
+ nArgs=0;
+ xFiFuncDesc->set_size_request(-1, 5 * xFiFuncDesc->get_text_height());
+
+ xCatBox->connect_changed(LINK( this, ScFunctionWin, SelComboHdl));
+ xFuncList->connect_changed(LINK( this, ScFunctionWin, SelTreeHdl));
+
+ xFuncList->connect_row_activated(LINK( this, ScFunctionWin, SetRowActivatedHdl));
+ xInsertButton->connect_clicked(LINK( this, ScFunctionWin, SetSelectionClickHdl));
+
+ xCatBox->set_active(0);
+
+ SelComboHdl(*xCatBox);
+}
+
+/*************************************************************************
+#* Member: ScFunctionWin
+#*------------------------------------------------------------------------
+#*
+#* Class: ScFunctionWin
+#*
+#* Function: Destructor of ScFunctionWin Class
+#*
+#* Input: ---
+#*
+#* Output: ---
+#*
+#************************************************************************/
+
+ScFunctionWin::~ScFunctionWin()
+{
+ xConfigChange.reset();
+ xConfigListener->dispose();
+ xConfigListener.clear();
+
+ xCatBox.reset();
+ xFuncList.reset();
+ xInsertButton.reset();
+ xFiFuncDesc.reset();
+}
+
+/*************************************************************************
+#* Member: UpdateFunctionList
+#*------------------------------------------------------------------------
+#*
+#* Class: ScFunctionWin
+#*
+#* Function: Updates the list of functions depending on the set category
+#*
+#* Input: ---
+#*
+#* Output: ---
+#*
+#************************************************************************/
+
+void ScFunctionWin::InitLRUList()
+{
+ ScFunctionMgr* pFuncMgr = ScGlobal::GetStarCalcFunctionMgr();
+ pFuncMgr->fillLastRecentlyUsedFunctions(aLRUList);
+
+ sal_Int32 nSelPos = xCatBox->get_active();
+
+ if (nSelPos == 0)
+ UpdateFunctionList();
+}
+
+/*************************************************************************
+#* Member: UpdateFunctionList
+#*------------------------------------------------------------------------
+#*
+#* Class: ScFunctionWin
+#*
+#* Function: Updates the list of last used functions.
+#*
+#* Input: ---
+#*
+#* Output: ---
+#*
+#************************************************************************/
+
+void ScFunctionWin::UpdateLRUList()
+{
+ if (pFuncDesc && pFuncDesc->nFIndex!=0)
+ {
+ ScModule* pScMod = SC_MOD();
+ pScMod->InsertEntryToLRUList(pFuncDesc->nFIndex);
+ }
+}
+
+/*************************************************************************
+#* Member: SetDescription
+#*------------------------------------------------------------------------
+#*
+#* Class: ScFunctionWin
+#*
+#* Function:
+#*
+#* Input: ---
+#*
+#* Output: ---
+#*
+#************************************************************************/
+
+void ScFunctionWin::SetDescription()
+{
+ xFiFuncDesc->set_label(OUString());
+ const ScFuncDesc* pDesc =
+ weld::fromId<const ScFuncDesc*>(xFuncList->get_selected_id());
+ if (pDesc)
+ {
+ pDesc->initArgumentInfo(); // full argument info is needed
+
+ OUString aBuf = xFuncList->get_selected_text() +
+ ":\n\n" +
+ pDesc->GetParamList() +
+ "\n\n" +
+ *pDesc->mxFuncDesc;
+
+ xFiFuncDesc->set_label(aBuf);
+ }
+}
+
+/*************************************************************************
+#* Member: UpdateFunctionList
+#*------------------------------------------------------------------------
+#*
+#* Class: ScFunctionWin
+#*
+#* Function: Updates the list of functions depending on the set category
+#*
+#* Input: ---
+#*
+#* Output: ---
+#*
+#************************************************************************/
+
+void ScFunctionWin::UpdateFunctionList()
+{
+ sal_Int32 nSelPos = xCatBox->get_active();
+ sal_Int32 nCategory = ( -1 != nSelPos )
+ ? (nSelPos-1) : 0;
+
+ xFuncList->clear();
+ xFuncList->freeze();
+
+ if ( nSelPos > 0 )
+ {
+ ScFunctionMgr* pFuncMgr = ScGlobal::GetStarCalcFunctionMgr();
+
+ const ScFuncDesc* pDesc = pFuncMgr->First( nCategory );
+ while ( pDesc )
+ {
+ xFuncList->append(weld::toId(pDesc), *(pDesc->mxFuncName));
+ pDesc = pFuncMgr->Next();
+ }
+ }
+ else // LRU list
+ {
+ for (const formula::IFunctionDescription* pDesc : aLRUList)
+ {
+ if (pDesc)
+ {
+ xFuncList->append(weld::toId(pDesc), pDesc->getFunctionName());
+ }
+ }
+ }
+
+ xFuncList->thaw();
+
+ if (xFuncList->n_children() > 0)
+ {
+ xFuncList->set_sensitive(true);
+ xFuncList->select(0);
+ }
+ else
+ {
+ xFuncList->set_sensitive(false);
+ }
+}
+
+/*************************************************************************
+#* Member: DoEnter
+#*------------------------------------------------------------------------
+#*
+#* Class: ScFunctionWin
+#*
+#* Function: Save input into document. Is called after clicking the
+#* Apply button or a double-click on the function list.
+#*
+#* Input: ---
+#*
+#* Output: ---
+#*
+#************************************************************************/
+
+void ScFunctionWin::DoEnter()
+{
+ OUStringBuffer aArgStr;
+ OUString aString=xFuncList->get_selected_text();
+ SfxViewShell* pCurSh = SfxViewShell::Current();
+ nArgs=0;
+
+ if(!aString.isEmpty())
+ {
+ OUString aFirstArgStr;
+ ScModule* pScMod = SC_MOD();
+ ScTabViewShell* pViewSh = dynamic_cast<ScTabViewShell*>( pCurSh );
+ ScInputHandler* pHdl = pScMod->GetInputHdl( pViewSh );
+ if(!pScMod->IsEditMode())
+ {
+ rtl::Reference<comphelper::ConfigurationListener> xDetectDisposed(xConfigListener);
+ pScMod->SetInputMode(SC_INPUT_TABLE);
+ // the above call can result in us being disposed
+ if (xDetectDisposed->isDisposed())
+ return;
+ aString = "=" + xFuncList->get_selected_text();
+ if (pHdl)
+ pHdl->ClearText();
+ }
+ const ScFuncDesc* pDesc =
+ weld::fromId<const ScFuncDesc*>(xFuncList->get_selected_id());
+ if (pDesc)
+ {
+ pFuncDesc=pDesc;
+ UpdateLRUList();
+ nArgs = pDesc->nArgCount;
+ if(nArgs>0)
+ {
+ // NOTE: Theoretically the first parameter could have the
+ // suppress flag as well, but practically it doesn't.
+ aFirstArgStr = pDesc->maDefArgNames[0];
+ aFirstArgStr = comphelper::string::strip(aFirstArgStr, ' ');
+ aFirstArgStr = aFirstArgStr.replaceAll(" ", "_");
+ aArgStr = aFirstArgStr;
+ if ( nArgs != VAR_ARGS && nArgs != PAIRED_VAR_ARGS )
+ { // no VarArgs or Fix plus VarArgs, but not VarArgs only
+ sal_uInt16 nFix;
+ if (nArgs >= PAIRED_VAR_ARGS)
+ nFix = nArgs - PAIRED_VAR_ARGS + 2;
+ else if (nArgs >= VAR_ARGS)
+ nFix = nArgs - VAR_ARGS + 1;
+ else
+ nFix = nArgs;
+ for ( sal_uInt16 nArg = 1;
+ nArg < nFix && !pDesc->pDefArgFlags[nArg].bOptional; nArg++ )
+ {
+ aArgStr.append("; ");
+ OUString sTmp = pDesc->maDefArgNames[nArg];
+ sTmp = comphelper::string::strip(sTmp, ' ');
+ sTmp = sTmp.replaceAll(" ", "_");
+ aArgStr.append(sTmp);
+ }
+ }
+ }
+ }
+ if (pHdl)
+ {
+ if (pHdl->GetEditString().isEmpty())
+ {
+ aString = "=" + xFuncList->get_selected_text();
+ }
+ EditView *pEdView=pHdl->GetActiveView();
+ if(pEdView!=nullptr) // @ needed because of crash during setting a name
+ {
+ if(nArgs>0)
+ {
+ pHdl->InsertFunction(aString);
+ pEdView->InsertText(aArgStr.makeStringAndClear(),true);
+ ESelection aESel=pEdView->GetSelection();
+ aESel.nEndPos = aESel.nStartPos + aFirstArgStr.getLength();
+ pEdView->SetSelection(aESel);
+ pHdl->DataChanged();
+ }
+ else
+ {
+ aString += "()";
+ pEdView->InsertText(aString);
+ pHdl->DataChanged();
+ }
+ }
+ }
+ InitLRUList();
+ }
+ if ( pCurSh )
+ {
+ vcl::Window* pShellWnd = pCurSh->GetWindow();
+
+ if ( pShellWnd )
+ pShellWnd->GrabFocus();
+ }
+
+}
+
+/*************************************************************************
+#* Handle: SelHdl
+#*------------------------------------------------------------------------
+#*
+#* Class: ScFunctionWin
+#*
+#* Function: A change of the category will update the list of functions.
+#*
+#* Input: ---
+#*
+#* Output: ---
+#*
+#************************************************************************/
+
+IMPL_LINK_NOARG(ScFunctionWin, SelComboHdl, weld::ComboBox&, void)
+{
+ UpdateFunctionList();
+ SetDescription();
+}
+
+IMPL_LINK_NOARG(ScFunctionWin, SelTreeHdl, weld::TreeView&, void)
+{
+ SetDescription();
+}
+
+/*************************************************************************
+#* Handle: SelHdl
+#*------------------------------------------------------------------------
+#*
+#* Class: ScFunctionWin
+#*
+#* Function: A change of the category will update the list of functions.
+#*
+#* Input: ---
+#*
+#* Output: ---
+#*
+#************************************************************************/
+
+IMPL_LINK_NOARG( ScFunctionWin, SetSelectionClickHdl, weld::Button&, void )
+{
+ DoEnter(); // saves the input
+}
+
+IMPL_LINK_NOARG( ScFunctionWin, SetRowActivatedHdl, weld::TreeView&, bool )
+{
+ DoEnter(); // saves the input
+ return true;
+}
+
+void EnglishFunctionNameChange::setProperty(const css::uno::Any &rProperty)
+{
+ ConfigurationListenerProperty::setProperty(rProperty);
+ m_pFunctionWin->InitLRUList();
+ m_pFunctionWin->UpdateFunctionList();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/formdlg/formdata.cxx b/sc/source/ui/formdlg/formdata.cxx
new file mode 100644
index 000000000..aabce7653
--- /dev/null
+++ b/sc/source/ui/formdlg/formdata.cxx
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <formdata.hxx>
+
+ScFormEditData::ScFormEditData()
+ : pInputHandler(nullptr)
+ , pScDocShell(nullptr)
+{
+ Reset();
+}
+
+ScFormEditData::~ScFormEditData() {}
+
+void ScFormEditData::SaveValues() { Reset(); }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/formdlg/formula.cxx b/sc/source/ui/formdlg/formula.cxx
new file mode 100644
index 000000000..6f4dfab2c
--- /dev/null
+++ b/sc/source/ui/formdlg/formula.cxx
@@ -0,0 +1,691 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <scitems.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/objsh.hxx>
+#include <svl/numformat.hxx>
+#include <svl/stritem.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <tools/urlobj.hxx>
+#include <formula/formulahelper.hxx>
+#include <formula/IFunctionDescription.hxx>
+#include <formula/errorcodes.hxx>
+
+#include <compiler.hxx>
+#include <formula.hxx>
+#include <formdata.hxx>
+#include <reffact.hxx>
+#include <document.hxx>
+#include <simpleformulacalc.hxx>
+#include <scmod.hxx>
+#include <inputhdl.hxx>
+#include <tabvwsh.hxx>
+#include <docsh.hxx>
+#include <funcdesc.hxx>
+#include <tokenarray.hxx>
+#include <sc.hrc>
+#include <servuno.hxx>
+#include <unonames.hxx>
+#include <externalrefmgr.hxx>
+
+#include <com/sun/star/table/CellAddress.hpp>
+#include <com/sun/star/sheet/XFormulaOpCodeMapper.hpp>
+#include <com/sun/star/sheet/XFormulaParser.hpp>
+
+using namespace formula;
+using namespace com::sun::star;
+
+// init/ shared functions for dialog
+
+ScFormulaDlg::ScFormulaDlg(SfxBindings* pB, SfxChildWindow* pCW,
+ weld::Window* pParent, const ScViewData& rViewData, 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();
+ m_pViewShell = nullptr;
+
+ // title has to be from the view that opened the dialog,
+ // even if it's not the current view
+
+ if ( pB )
+ {
+ SfxDispatcher* pMyDisp = pB->GetDispatcher();
+ if (pMyDisp)
+ {
+ SfxViewFrame* pMyViewFrm = pMyDisp->GetFrame();
+ if (pMyViewFrm)
+ {
+ m_pViewShell = dynamic_cast<ScTabViewShell*>( pMyViewFrm->GetViewShell() );
+ if( m_pViewShell )
+ m_pViewShell->UpdateInputHandler(true);
+ }
+ }
+ }
+
+ m_pDoc = &rViewData.GetDocument();
+ m_xParser.set(ScServiceProvider::MakeInstance(ScServiceProvider::Type::FORMULAPARS,
+ static_cast<ScDocShell*>(m_pDoc->GetDocumentShell())),uno::UNO_QUERY);
+ uno::Reference< beans::XPropertySet> xSet(m_xParser,uno::UNO_QUERY);
+ xSet->setPropertyValue(SC_UNO_COMPILEFAP, uno::Any(true));
+
+ m_xOpCodeMapper.set(ScServiceProvider::MakeInstance(ScServiceProvider::Type::OPCODEMAPPER,
+ static_cast<ScDocShell*>(m_pDoc->GetDocumentShell())),uno::UNO_QUERY);
+
+ ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl(m_pViewShell);
+
+ assert(pInputHdl && "Missing input handler :-/");
+
+ pInputHdl->NotifyChange( nullptr );
+
+ ScFormulaReferenceHelper::enableInput( true );
+ ScFormulaReferenceHelper::EnableSpreadsheets();
+ m_aHelper.Init();
+ m_aHelper.SetDispatcherLock( true );
+
+ notifyChange();
+ fill();
+
+ ScFormEditData* pData = m_pViewShell->GetFormEditData();
+ if (pData)
+ return;
+
+ pScMod->SetRefInputHdl(pInputHdl);
+
+ m_pDoc = &rViewData.GetDocument();
+ SCCOL nCol = rViewData.GetCurX();
+ SCROW nRow = rViewData.GetCurY();
+ SCTAB nTab = rViewData.GetTabNo();
+ m_CursorPos = ScAddress( nCol, nRow, nTab );
+
+ m_pViewShell->InitFormEditData(); // create new
+ pData = m_pViewShell->GetFormEditData();
+ pData->SetInputHandler(pInputHdl);
+ pData->SetDocShell(rViewData.GetDocShell());
+
+ OSL_ENSURE(pData,"FormEditData not available");
+
+ formula::FormulaDlgMode eMode = FormulaDlgMode::Formula; // default...
+
+ // edit if formula exists
+
+ OUString aFormula = m_pDoc->GetFormula( nCol, nRow, nTab );
+ bool bEdit = ( aFormula.getLength() > 1 );
+ bool bMatrix = false;
+ if ( bEdit )
+ {
+ bMatrix = CheckMatrix(aFormula);
+
+ sal_Int32 nFStart = 0;
+ sal_Int32 nFEnd = 0;
+ if ( GetFormulaHelper().GetNextFunc( aFormula, false, nFStart, &nFEnd) )
+ {
+ pInputHdl->InputReplaceSelection( aFormula );
+ pInputHdl->InputSetSelection( nFStart, nFEnd );
+ sal_Int32 PrivStart, PrivEnd;
+ pInputHdl->InputGetSelection( PrivStart, PrivEnd);
+
+ eMode = SetMeText(pInputHdl->GetFormString(),PrivStart, PrivEnd, bMatrix, true, true);
+ pData->SetFStart( nFStart );
+ }
+ else
+ bEdit = false;
+ }
+
+ if ( !bEdit )
+ {
+ OUString aNewFormula('=');
+ if ( aFormula.startsWith("=") )
+ aNewFormula = aFormula;
+
+ pInputHdl->InputReplaceSelection( aNewFormula );
+ pInputHdl->InputSetSelection( 1, aNewFormula.getLength()+1 );
+ sal_Int32 PrivStart, PrivEnd;
+ pInputHdl->InputGetSelection( PrivStart, PrivEnd);
+ SetMeText(pInputHdl->GetFormString(),PrivStart, PrivEnd,bMatrix,false,false);
+
+ pData->SetFStart( 1 ); // after "="
+ }
+
+ pData->SetMode( eMode );
+ OUString rStrExp = GetMeText();
+
+ Update(rStrExp);
+
+}
+
+void ScFormulaDlg::notifyChange()
+{
+ ScInputHandler* pInputHdl = m_pViewShell->GetInputHandler();
+ if ( pInputHdl )
+ pInputHdl->NotifyChange( nullptr );
+}
+
+void ScFormulaDlg::fill()
+{
+ ScModule* pScMod = SC_MOD();
+ ScFormEditData* pData = static_cast<ScFormEditData*>(getFormEditData());
+ notifyChange();
+ OUString rStrExp;
+ if (!pData)
+ return;
+
+ // data exists -> restore state (after switch)
+ // don't reinitialise m_pDoc and m_CursorPos
+ //pDoc = rViewData.GetDocument();
+ if(IsInputHdl(pData->GetInputHandler()))
+ {
+ pScMod->SetRefInputHdl(pData->GetInputHandler());
+ }
+ else
+ {
+ ScTabViewShell* pTabViewShell;
+ ScInputHandler* pInputHdl = GetNextInputHandler(pData->GetDocShell(),&pTabViewShell);
+
+ if ( pInputHdl == nullptr ) //no more InputHandler for DocShell
+ {
+ disableOk();
+ pInputHdl = pScMod->GetInputHdl();
+ }
+ else
+ {
+ pInputHdl->SetRefViewShell(pTabViewShell);
+ }
+ pScMod->SetRefInputHdl(pInputHdl);
+ pData->SetInputHandler(pInputHdl);
+ }
+
+ OUString aOldFormulaTmp(pData->GetInputHandler()->GetFormString());
+ pData->GetInputHandler()->InputSetSelection( 0, aOldFormulaTmp.getLength());
+
+ rStrExp=pData->GetUndoStr();
+ pData->GetInputHandler()->InputReplaceSelection(rStrExp);
+
+ SetMeText(rStrExp);
+
+ Update();
+ // switch back, maybe new Doc has been opened
+ pScMod->SetRefInputHdl(nullptr);
+}
+
+ScFormulaDlg::~ScFormulaDlg() COVERITY_NOEXCEPT_FALSE
+{
+ ScFormEditData* pData = m_pViewShell->GetFormEditData();
+
+ m_aHelper.dispose();
+
+ if (pData) // close doesn't destroy;
+ {
+ //set back reference input handler
+ SC_MOD()->SetRefInputHdl(nullptr);
+ StoreFormEditData(pData);
+ }
+
+ m_pViewShell->ClearFormEditData();
+}
+
+bool ScFormulaDlg::IsInputHdl(const ScInputHandler* pHdl)
+{
+ bool bAlive = false;
+
+ // belongs InputHandler to a ViewShell?
+
+ SfxViewShell* pSh = SfxViewShell::GetFirst( true, checkSfxViewShell<ScTabViewShell> );
+ while ( pSh && !bAlive )
+ {
+ if (static_cast<ScTabViewShell*>(pSh)->GetInputHandler() == pHdl)
+ bAlive = true;
+ pSh = SfxViewShell::GetNext( *pSh, true, checkSfxViewShell<ScTabViewShell> );
+ }
+
+ return bAlive;
+
+}
+
+ScInputHandler* ScFormulaDlg::GetNextInputHandler(const ScDocShell* pDocShell, ScTabViewShell** ppViewSh)
+{
+ ScInputHandler* pHdl=nullptr;
+
+ SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell );
+ while( pFrame && pHdl==nullptr)
+ {
+ SfxViewShell* p = pFrame->GetViewShell();
+ ScTabViewShell* pViewSh = dynamic_cast< ScTabViewShell *>( p );
+ if(pViewSh!=nullptr)
+ {
+ pHdl=pViewSh->GetInputHandler();
+ if(ppViewSh!=nullptr) *ppViewSh=pViewSh;
+ }
+ pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell );
+ }
+
+ return pHdl;
+}
+
+void ScFormulaDlg::Close()
+{
+ if (IsClosing())
+ return;
+
+ DoEnter();
+}
+
+// functions for right side
+
+bool ScFormulaDlg::calculateValue( const OUString& rStrExp, OUString& rStrResult, bool bMatrixFormula )
+{
+ std::optional<ScSimpleFormulaCalculator> pFCell(std::in_place,
+ *m_pDoc, m_CursorPos, rStrExp, bMatrixFormula);
+ pFCell->SetLimitString(true);
+
+ // HACK! to avoid neither #REF! from ColRowNames
+ // if a name is added as actually range in the overall formula,
+ // but is interpreted at the individual representation as single-cell reference
+ bool bColRowName = pFCell->HasColRowName();
+ if ( bColRowName )
+ {
+ // ColRowName from RPN-Code?
+ if ( pFCell->GetCode()->GetCodeLen() <= 1 )
+ { // ==1: area
+ // ==0: would be an area if...
+ OUString aBraced = "(" + rStrExp + ")";
+ pFCell.emplace(*m_pDoc, m_CursorPos, aBraced, bMatrixFormula);
+ pFCell->SetLimitString(true);
+ }
+ else
+ bColRowName = false;
+ }
+
+ FormulaError nErrCode = pFCell->GetErrCode();
+ if ( nErrCode == FormulaError::NONE || pFCell->IsMatrix() )
+ {
+ SvNumberFormatter& aFormatter = *(m_pDoc->GetFormatTable());
+ const Color* pColor;
+ if (pFCell->IsMatrix())
+ {
+ rStrResult = pFCell->GetString().getString();
+ }
+ else if (pFCell->IsValue())
+ {
+ double n = pFCell->GetValue();
+ sal_uLong nFormat = aFormatter.GetStandardFormat( n, 0,
+ pFCell->GetFormatType(), ScGlobal::eLnge );
+ aFormatter.GetOutputString( n, nFormat, rStrResult, &pColor );
+ }
+ else
+ {
+ sal_uLong nFormat = aFormatter.GetStandardFormat(
+ pFCell->GetFormatType(), ScGlobal::eLnge);
+ aFormatter.GetOutputString( pFCell->GetString().getString(), nFormat,
+ rStrResult, &pColor );
+ // Indicate it's a string, so a number string doesn't look numeric.
+ // Escape embedded quotation marks first by doubling them, as
+ // usual. Actually the result can be copy-pasted from the result
+ // box as literal into a formula expression.
+ rStrResult = "\"" + rStrResult.replaceAll( "\"", "\"\"") + "\"";
+ }
+
+ ScRange aTestRange;
+ if ( bColRowName || (aTestRange.Parse(rStrExp, *m_pDoc) & ScRefFlags::VALID) )
+ rStrResult += " ...";
+ // area
+ }
+ else
+ rStrResult += ScGlobal::GetErrorString(nErrCode);
+
+ return true;
+}
+
+std::shared_ptr<formula::FormulaCompiler> ScFormulaDlg::getCompiler() const
+{
+ if (!m_xCompiler)
+ m_xCompiler = std::make_shared<ScCompiler>(*m_pDoc, m_CursorPos, m_pDoc->GetGrammar());
+ return m_xCompiler;
+}
+
+std::unique_ptr<formula::FormulaCompiler> ScFormulaDlg::createCompiler( formula::FormulaTokenArray& rArray ) const
+{
+ ScCompiler* pCompiler = nullptr;
+ ScTokenArray* pArr = dynamic_cast<ScTokenArray*>(&rArray);
+ assert(pArr); // violation of contract and not created using convertToTokenArray()?
+ if (pArr)
+ pCompiler = new ScCompiler(*m_pDoc, m_CursorPos, *pArr, m_pDoc->GetGrammar());
+ return std::unique_ptr<formula::FormulaCompiler>(pCompiler);
+}
+
+// virtual methods of ScAnyRefDlg:
+void ScFormulaDlg::RefInputStart( formula::RefEdit* pEdit, formula::RefButton* pButton )
+{
+ pEdit->SelectAll();
+ ::std::pair<formula::RefButton*,formula::RefEdit*> aPair = RefInputStartBefore( pEdit, pButton );
+ m_aHelper.RefInputStart( aPair.second, aPair.first);
+ RefInputStartAfter();
+}
+
+void ScFormulaDlg::RefInputDone( bool bForced )
+{
+ m_aHelper.RefInputDone( bForced );
+ RefInputDoneAfter( bForced );
+}
+
+void ScFormulaDlg::SetReference( const ScRange& rRef, ScDocument& rRefDoc )
+{
+ const IFunctionDescription* pFunc = getCurrentFunctionDescription();
+ if ( !(pFunc && pFunc->getSuppressedArgumentCount() > 0) )
+ return;
+
+ Selection theSel;
+ bool bRefNull = UpdateParaWin(theSel);
+
+ if ( rRef.aStart != rRef.aEnd && bRefNull )
+ {
+ RefInputStart(GetActiveEdit());
+ }
+
+ // Pointer-selected => absolute range references for the non-single
+ // dimensions, so in the other dimension (if any) it's still
+ // copy-adjustable.
+ constexpr ScRefFlags eColFlags = ScRefFlags::COL_ABS | ScRefFlags::COL2_ABS;
+ constexpr ScRefFlags eRowFlags = ScRefFlags::ROW_ABS | ScRefFlags::ROW2_ABS;
+ ScRefFlags eRangeFlags = ScRefFlags::ZERO;
+ if (rRef.aStart.Col() != rRef.aEnd.Col())
+ eRangeFlags |= eColFlags;
+ if (rRef.aStart.Row() != rRef.aEnd.Row())
+ eRangeFlags |= eRowFlags;
+ OUString aRefStr;
+ bool bOtherDoc = (&rRefDoc != m_pDoc && rRefDoc.GetDocumentShell()->HasName());
+ if ( bOtherDoc )
+ {
+ // reference to other document - like inputhdl.cxx
+
+ OSL_ENSURE(rRef.aStart.Tab()==rRef.aEnd.Tab(), "nStartTab!=nEndTab");
+
+ // Sheet always 3D and absolute.
+ OUString aTmp( rRef.Format(rRefDoc, ScRefFlags::VALID | ScRefFlags::TAB_ABS_3D | eRangeFlags));
+
+ SfxObjectShell* pObjSh = rRefDoc.GetDocumentShell();
+
+ // #i75893# convert escaped URL of the document to something user friendly
+// OUString aFileName = pObjSh->GetMedium()->GetName();
+ OUString aFileName = pObjSh->GetMedium()->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::Unambiguous );
+
+ aRefStr = "'" + aFileName + "'#" + aTmp;
+ }
+ else
+ {
+ // We can't use ScRange::Format here because in R1C1 mode we need
+ // to display the reference position relative to the cursor
+ // position.
+ ScTokenArray aArray(rRefDoc);
+ ScComplexRefData aRefData;
+ aRefData.InitRangeRel(rRefDoc, rRef, m_CursorPos);
+ if ((eRangeFlags & eColFlags) == eColFlags)
+ {
+ aRefData.Ref1.SetAbsCol( rRef.aStart.Col() );
+ aRefData.Ref2.SetAbsCol( rRef.aEnd.Col() );
+ }
+ if ((eRangeFlags & eRowFlags) == eRowFlags)
+ {
+ aRefData.Ref1.SetAbsRow( rRef.aStart.Row() );
+ aRefData.Ref2.SetAbsRow( rRef.aEnd.Row() );
+ }
+ bool bSingle = aRefData.Ref1 == aRefData.Ref2;
+ if (m_CursorPos.Tab() != rRef.aStart.Tab())
+ {
+ // pointer-selected => absolute sheet reference
+ aRefData.Ref1.SetAbsTab( rRef.aStart.Tab() );
+ aRefData.Ref1.SetFlag3D(true);
+ }
+ if (bSingle)
+ aArray.AddSingleReference(aRefData.Ref1);
+ else
+ aArray.AddDoubleReference(aRefData);
+ ScCompiler aComp(*m_pDoc, m_CursorPos, aArray, m_pDoc->GetGrammar());
+ OUStringBuffer aBuf;
+ aComp.CreateStringFromTokenArray(aBuf);
+ aRefStr = aBuf.makeStringAndClear();
+ }
+
+ UpdateParaWin(theSel,aRefStr);
+}
+
+bool ScFormulaDlg::IsRefInputMode() const
+{
+ const IFunctionDescription* pDesc = getCurrentFunctionDescription();
+ bool bRef = (pDesc && (pDesc->getSuppressedArgumentCount() > 0)) && (m_pDoc != nullptr);
+ return bRef;
+}
+
+bool ScFormulaDlg::IsDocAllowed(SfxObjectShell* pDocSh) const
+{
+ // not allowed: different from this doc, and no name
+ // pDocSh is always a ScDocShell
+ return !pDocSh || &static_cast<ScDocShell*>(pDocSh)->GetDocument() == m_pDoc || pDocSh->HasName(); // everything else is allowed
+}
+
+void ScFormulaDlg::SetActive()
+{
+ const IFunctionDescription* pFunc = getCurrentFunctionDescription();
+ if ( pFunc && pFunc->getSuppressedArgumentCount() > 0 )
+ {
+ RefInputDone();
+ SetEdSelection();
+ }
+}
+
+void ScFormulaDlg::SaveLRUEntry(const ScFuncDesc* pFuncDescP)
+{
+ if (pFuncDescP && pFuncDescP->nFIndex!=0)
+ {
+ ScModule* pScMod = SC_MOD();
+ pScMod->InsertEntryToLRUList(pFuncDescP->nFIndex);
+ }
+}
+
+void ScFormulaDlg::doClose(bool /*_bOk*/)
+{
+ m_aHelper.DoClose( ScFormulaDlgWrapper::GetChildWindowId() );
+}
+void ScFormulaDlg::insertEntryToLRUList(const formula::IFunctionDescription* _pDesc)
+{
+ const ScFuncDesc* pDesc = dynamic_cast<const ScFuncDesc*>(_pDesc);
+ SaveLRUEntry(pDesc);
+}
+void ScFormulaDlg::showReference(const OUString& _sFormula)
+{
+ ShowReference(_sFormula);
+}
+void ScFormulaDlg::ShowReference(const OUString& _sFormula)
+{
+ m_aHelper.ShowReference(_sFormula);
+}
+void ScFormulaDlg::HideReference( bool bDoneRefMode )
+{
+ m_aHelper.HideReference(bDoneRefMode);
+}
+void ScFormulaDlg::ViewShellChanged()
+{
+ ScFormulaReferenceHelper::ViewShellChanged();
+}
+void ScFormulaDlg::AddRefEntry( )
+{
+
+}
+bool ScFormulaDlg::IsTableLocked( ) const
+{
+ // default: reference input can also be used to switch the table
+ return false;
+}
+
+void ScFormulaDlg::ToggleCollapsed( formula::RefEdit* pEdit, formula::RefButton* pButton)
+{
+ m_aHelper.ToggleCollapsed(pEdit,pButton);
+}
+
+void ScFormulaDlg::ReleaseFocus( formula::RefEdit* pEdit)
+{
+ m_aHelper.ReleaseFocus(pEdit);
+}
+
+void ScFormulaDlg::dispatch(bool _bOK, bool _bMatrixChecked)
+{
+ SfxBoolItem aRetItem( SID_DLG_RETOK, _bOK );
+ SfxBoolItem aMatItem( SID_DLG_MATRIX, _bMatrixChecked );
+ SfxStringItem aStrItem( SCITEM_STRING, getCurrentFormula() );
+
+ // if edit line is empty (caused by document switching) -> string is empty
+ // -> don't delete old formula
+ if ( aStrItem.GetValue().isEmpty() )
+ aRetItem.SetValue( false ); // sal_False = Cancel
+
+ m_aHelper.SetDispatcherLock( false ); // turn off modal-mode
+
+ clear();
+
+ GetBindings().GetDispatcher()->ExecuteList( SID_INS_FUNCTION,
+ SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
+ { &aRetItem, &aStrItem, &aMatItem });
+}
+void ScFormulaDlg::setDispatcherLock( bool bLock )
+{
+ m_aHelper.SetDispatcherLock( bLock );
+}
+void ScFormulaDlg::deleteFormData()
+{
+ if (m_pViewShell)
+ m_pViewShell->ClearFormEditData(); // pData is invalid!
+}
+void ScFormulaDlg::clear()
+{
+ m_pDoc = nullptr;
+
+ //restore reference inputhandler
+ ScModule* pScMod = SC_MOD();
+ pScMod->SetRefInputHdl(nullptr);
+
+ // force Enable() of edit line
+ ScTabViewShell* pScViewShell = dynamic_cast<ScTabViewShell*>( SfxViewShell::Current() );
+ if ( pScViewShell )
+ pScViewShell->UpdateInputHandler();
+}
+void ScFormulaDlg::switchBack()
+{
+ // back to the document
+ // (foreign doc could be above - #34222#)
+ ScInputHandler* pHdl = m_pViewShell->GetInputHandler();
+ if ( pHdl )
+ {
+ pHdl->ViewShellGone(nullptr); // -> get active view
+ pHdl->ShowRefFrame();
+ }
+
+ // restore current chart (cause mouse-RefInput)
+ ScTabViewShell* pScViewShell = dynamic_cast<ScTabViewShell*>( SfxViewShell::Current() );
+ if ( !pScViewShell )
+ return;
+
+ ScViewData& rVD=pScViewShell->GetViewData();
+ SCTAB nExecTab = m_CursorPos.Tab();
+ if ( nExecTab != rVD.GetTabNo() )
+ pScViewShell->SetTabNo( nExecTab );
+
+ SCROW nRow = m_CursorPos.Row();
+ SCCOL nCol = m_CursorPos.Col();
+
+ if(rVD.GetCurX()!=nCol || rVD.GetCurY()!=nRow)
+ pScViewShell->SetCursor(nCol,nRow);
+}
+formula::FormEditData* ScFormulaDlg::getFormEditData() const
+{
+ ScTabViewShell* pViewShell = m_pViewShell;
+ if (pViewShell)
+ return pViewShell->GetFormEditData();
+ return nullptr;
+}
+void ScFormulaDlg::setCurrentFormula(const OUString& _sReplacement)
+{
+ ScModule* pScMod = SC_MOD();
+ {
+ //fdo#69971 We need the EditEngine Modification handler of the inputbar that we
+ //are feeding to be disabled while this dialog is open. Otherwise we end up in
+ //a situation where...
+ //a) this ScFormulaDlg changes the editengine
+ //b) the modify callback gets called
+ //c) which also modifies the editengine
+ //d) on return from that modify handler the editengine attempts to use
+ // old node pointers which were replaced and removed by c
+ //
+ //We turn it off in the ctor and back on in the dtor, but if calc has
+ //to repaint, e.g. when switching to another window and back, then in
+ //ScMultiTextWnd::Paint a new editengine will have been created via
+ //GetEditView with its default Modification handler enabled. So ensure
+ //its off when we will access it via InputReplaceSelection
+ pScMod->InputTurnOffWinEngine();
+ }
+ pScMod->InputReplaceSelection(_sReplacement);
+}
+void ScFormulaDlg::setSelection(sal_Int32 _nStart, sal_Int32 _nEnd)
+{
+ ScModule* pScMod = SC_MOD();
+ pScMod->InputSetSelection( _nStart, _nEnd );
+}
+void ScFormulaDlg::getSelection(sal_Int32& _nStart, sal_Int32& _nEnd) const
+{
+ ScModule* pScMod = SC_MOD();
+ pScMod->InputGetSelection( _nStart, _nEnd );
+}
+OUString ScFormulaDlg::getCurrentFormula() const
+{
+ ScFormEditData* pData = m_pViewShell->GetFormEditData();
+ if (pData && pData->GetInputHandler())
+ return pData->GetInputHandler()->GetFormString();
+ return "";
+}
+formula::IFunctionManager* ScFormulaDlg::getFunctionManager()
+{
+ return ScGlobal::GetStarCalcFunctionMgr();
+}
+uno::Reference< sheet::XFormulaParser> ScFormulaDlg::getFormulaParser() const
+{
+ return m_xParser;
+}
+uno::Reference< sheet::XFormulaOpCodeMapper> ScFormulaDlg::getFormulaOpCodeMapper() const
+{
+ return m_xOpCodeMapper;
+}
+
+table::CellAddress ScFormulaDlg::getReferencePosition() const
+{
+ return table::CellAddress(m_CursorPos.Tab(), m_CursorPos.Col(), m_CursorPos.Row());
+}
+
+::std::unique_ptr<formula::FormulaTokenArray> ScFormulaDlg::convertToTokenArray(const uno::Sequence< sheet::FormulaToken >& _aTokenList)
+{
+ ::std::unique_ptr<formula::FormulaTokenArray> pArray(new ScTokenArray(*m_pDoc));
+ pArray->Fill(_aTokenList, m_pDoc->GetSharedStringPool(), m_pDoc->GetExternalRefManager());
+ return pArray;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */