Version 4.0.0.1, tag libreoffice-4.0.0.1
[LibreOffice.git] / formula / source / ui / dlg / formula.cxx
blob409059335c30f30744bf25dd66d409c45c3880e4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sfx2/dispatch.hxx>
21 #include <sfx2/docfile.hxx>
22 #include <sfx2/viewfrm.hxx>
23 #include <vcl/svapp.hxx>
24 #include <vcl/mnemonic.hxx>
25 #include <vcl/tabpage.hxx>
26 #include <vcl/tabctrl.hxx>
27 #include <vcl/lstbox.hxx>
28 #include <vcl/group.hxx>
29 #include <vcl/wall.hxx>
31 #include <svtools/stdctrl.hxx>
32 #include <svtools/svmedit.hxx>
33 #include <svtools/treelistbox.hxx>
34 #include <svl/stritem.hxx>
35 #include <svl/zforlist.hxx>
36 #include <svl/eitem.hxx>
38 #include <unotools/charclass.hxx>
39 #include <tools/diagnose_ex.h>
41 #include "formdlgs.hrc"
42 #include "funcpage.hxx"
43 #include "formula/formula.hxx"
44 #include "formula/IFunctionDescription.hxx"
45 #include "formula/FormulaCompiler.hxx"
46 #include "formula/token.hxx"
47 #include "formula/tokenarray.hxx"
48 #include "formula/formdata.hxx"
49 #include "formula/formulahelper.hxx"
50 #include "structpg.hxx"
51 #include "parawin.hxx"
52 #include "ModuleHelper.hxx"
53 #include "ForResId.hrc"
54 #include <com/sun/star/sheet/FormulaToken.hpp>
55 #include <com/sun/star/sheet/FormulaLanguage.hpp>
56 #include <com/sun/star/sheet/FormulaMapGroup.hpp>
57 #include <com/sun/star/sheet/FormulaMapGroupSpecialOffset.hpp>
58 #include <com/sun/star/beans/XPropertySet.hpp>
59 #include <boost/ref.hpp>
60 #include <boost/shared_ptr.hpp>
61 #include <comphelper/processfactory.hxx>
62 #include <comphelper/string.hxx>
63 #include <map>
65 #define TOKEN_OPEN 0
66 #define TOKEN_CLOSE 1
67 #define TOKEN_SEP 2
68 namespace formula
70 using namespace ::com::sun::star;
72 class OFormulaToken : public IFormulaToken
74 sal_Int32 m_nParaCount;
75 bool m_bIsFunction;
77 public:
78 OFormulaToken(bool _bFunction,sal_Int32 _nParaCount) : m_nParaCount(_nParaCount),m_bIsFunction(_bFunction){}
80 virtual ~OFormulaToken() {}
82 virtual bool isFunction() const { return m_bIsFunction; }
83 virtual sal_uInt32 getArgumentCount() const { return m_nParaCount; }
87 class FormulaDlg_Impl
89 public:
90 ::std::pair<RefButton*,RefEdit*>
91 RefInputStartBefore( RefEdit* pEdit, RefButton* pButton );
92 void RefInputStartAfter( RefEdit* pEdit, RefButton* pButton );
93 void RefInputDoneAfter( sal_Bool bForced );
94 sal_Bool CalcValue( const String& rStrExp, String& rStrResult );
95 sal_Bool CalcStruct( const String& rStrExp);
96 void UpdateValues();
97 void DeleteArgs();
98 xub_StrLen GetFunctionPos(xub_StrLen nPos);
99 void ClearAllParas();
101 void MakeTree(IStructHelper* _pTree,SvTreeListEntry* pParent,FormulaToken* _pToken,long Count);
102 void fillTree(IStructHelper* _pTree);
103 void UpdateTokenArray( const String& rStrExp);
104 String RepairFormula(const String& aFormula);
105 void FillDialog(sal_Bool nFlag=sal_True);
106 void EditNextFunc( sal_Bool bForward, xub_StrLen nFStart=NOT_FOUND );
107 void EditThisFunc(xub_StrLen nFStart);
109 void StoreFormEditData(FormEditData* pEditData);
111 void UpdateArgInput( sal_uInt16 nOffset, sal_uInt16 nInput );
112 void Update();
113 void Update(const String& _sExp);
115 void SaveArg( sal_uInt16 nEd );
116 void UpdateSelection();
117 void DoEnter( sal_Bool bOk );
118 void FillListboxes();
119 void FillControls(sal_Bool &rbNext, sal_Bool &rbPrev);
121 FormulaDlgMode SetMeText(const String& _sText,xub_StrLen PrivStart, xub_StrLen PrivEnd,sal_Bool bMatrix,sal_Bool _bSelect,sal_Bool _bUpdate);
122 void SetMeText(const String& _sText);
123 sal_Bool CheckMatrix(String& aFormula /*IN/OUT*/);
125 void SetEdSelection();
127 sal_Bool UpdateParaWin(Selection& _rSelection);
128 void UpdateParaWin(const Selection& _rSelection,const String& _sRefStr);
130 void SetData(xub_StrLen nFStart,xub_StrLen nNextFStart,xub_StrLen nNextFEnd,xub_StrLen& PrivStart,xub_StrLen& PrivEnd);
131 void PreNotify( NotifyEvent& rNEvt );
133 RefEdit* GetCurrRefEdit();
135 const FormulaHelper& GetFormulaHelper() const;
136 uno::Reference< sheet::XFormulaOpCodeMapper > GetFormulaOpCodeMapper() const;
138 DECL_LINK( ModifyHdl, ParaWin* );
139 DECL_LINK( FxHdl, ParaWin* );
141 DECL_LINK(MatrixHdl, void *);
142 DECL_LINK(FormulaHdl, void *);
143 DECL_LINK(FormulaCursorHdl, void *);
144 DECL_LINK( BtnHdl, PushButton* );
145 DECL_LINK( GetEdFocusHdl, ArgInput* );
146 DECL_LINK( GetFxFocusHdl, ArgInput* );
147 DECL_LINK(DblClkHdl, void *);
148 DECL_LINK(FuncSelHdl, void *);
149 DECL_LINK(StructSelHdl, void *);
150 public:
151 mutable uno::Reference< sheet::XFormulaOpCodeMapper> m_xOpCodeMapper;
152 uno::Sequence< sheet::FormulaToken > m_aTokenList;
153 ::std::auto_ptr<FormulaTokenArray> m_pTokenArray;
154 mutable uno::Sequence< sheet::FormulaOpCodeMapEntry > m_aSpecialOpCodes;
155 mutable const sheet::FormulaOpCodeMapEntry* m_pSpecialOpCodesEnd;
156 mutable uno::Sequence< sheet::FormulaToken > m_aSeparatorsOpCodes;
157 mutable uno::Sequence< sheet::FormulaOpCodeMapEntry > m_aFunctionOpCodes;
158 mutable const sheet::FormulaOpCodeMapEntry* m_pFunctionOpCodesEnd;
159 mutable uno::Sequence< sheet::FormulaOpCodeMapEntry > m_aUnaryOpCodes;
160 mutable const sheet::FormulaOpCodeMapEntry* m_pUnaryOpCodesEnd;
161 mutable uno::Sequence< sheet::FormulaOpCodeMapEntry > m_aBinaryOpCodes;
162 mutable const sheet::FormulaOpCodeMapEntry* m_pBinaryOpCodesEnd;
163 ::std::vector< ::boost::shared_ptr<OFormulaToken> > m_aTokens;
164 ::std::map<FormulaToken*,sheet::FormulaToken> m_aTokenMap;
165 IFormulaEditorHelper* m_pHelper;
166 Dialog* m_pParent;
167 IControlReferenceHandler* m_pDlg;
168 TabControl aTabCtrl;
169 GroupBox aGEdit; //! MUST be placed before pParaWin for initializing
170 ParaWin* pParaWin;
171 FixedText aFtHeadLine;
172 FixedInfo aFtFuncName;
173 FixedInfo aFtFuncDesc;
175 FixedText aFtEditName;
177 FixedText aFtResult;
178 ValWnd aWndResult;
180 FixedText aFtFormula;
181 EditBox aMEFormula;
183 CheckBox aBtnMatrix;
184 HelpButton aBtnHelp;
185 CancelButton aBtnCancel;
187 PushButton aBtnBackward;
188 PushButton aBtnForward;
189 OKButton aBtnEnd;
191 RefEdit aEdRef;
192 RefButton aRefBtn;
194 FixedText aFtFormResult;
195 ValWnd aWndFormResult;
197 RefEdit* pTheRefEdit;
198 RefButton* pTheRefButton;
199 FuncPage* pFuncPage;
200 StructPage* pStructPage;
201 String aOldFormula;
202 sal_Bool bStructUpdate;
203 MultiLineEdit* pMEdit;
204 sal_Bool bUserMatrixFlag;
205 Timer aTimer;
207 const String aTitle1;
208 const String aTitle2;
209 const String aTxtEnd;
210 const String aTxtOk; // behind aBtnEnd
211 FormulaHelper
212 m_aFormulaHelper;
214 rtl::OString m_aEditHelpId;
216 rtl::OString aOldHelp;
217 rtl::OString aOldUnique;
218 rtl::OString aActivWinId;
219 sal_Bool bIsShutDown;
221 Font aFntBold;
222 Font aFntLight;
223 sal_uInt16 nEdFocus;
224 sal_Bool bEditFlag;
225 const IFunctionDescription* pFuncDesc;
226 xub_StrLen nArgs;
227 ::std::vector< ::rtl::OUString > m_aArguments;
228 Selection aFuncSel;
230 FormulaDlg_Impl(Dialog* pParent
231 , bool _bSupportFunctionResult
232 , bool _bSupportResult
233 , bool _bSupportMatrix
234 ,IFormulaEditorHelper* _pHelper
235 ,const IFunctionManager* _pFunctionMgr
236 ,IControlReferenceHandler* _pDlg);
237 ~FormulaDlg_Impl();
240 FormulaDlg_Impl::FormulaDlg_Impl(Dialog* pParent
241 , bool _bSupportFunctionResult
242 , bool _bSupportResult
243 , bool _bSupportMatrix
244 ,IFormulaEditorHelper* _pHelper
245 ,const IFunctionManager* _pFunctionMgr
246 ,IControlReferenceHandler* _pDlg)
248 m_pHelper (_pHelper),
249 m_pParent (pParent),
250 m_pDlg (_pDlg),
251 aTabCtrl ( pParent, ModuleRes( TC_FUNCTION ) ),
252 aGEdit ( pParent, ModuleRes( GB_EDIT ) ),
253 aFtHeadLine ( pParent, ModuleRes( FT_HEADLINE ) ),
254 aFtFuncName ( pParent, ModuleRes( FT_FUNCNAME ) ),
255 aFtFuncDesc ( pParent, ModuleRes( FT_FUNCDESC ) ),
256 aFtEditName ( pParent, ModuleRes( FT_EDITNAME ) ),
257 aFtResult ( pParent, ModuleRes( FT_RESULT ) ),
258 aWndResult ( pParent, ModuleRes( WND_RESULT ) ),
260 aFtFormula ( pParent, ModuleRes( FT_FORMULA ) ),
261 aMEFormula ( pParent, ModuleRes( ED_FORMULA ) ),
262 aBtnMatrix ( pParent, ModuleRes( BTN_MATRIX ) ),
263 aBtnHelp ( pParent, ModuleRes( BTN_HELP ) ),
264 aBtnCancel ( pParent, ModuleRes( BTN_CANCEL ) ),
265 aBtnBackward ( pParent, ModuleRes( BTN_BACKWARD ) ),
266 aBtnForward ( pParent, ModuleRes( BTN_FORWARD ) ),
267 aBtnEnd ( pParent, ModuleRes( BTN_END ) ),
268 aEdRef ( pParent, _pDlg, ModuleRes( ED_REF) ),
269 aRefBtn ( pParent, ModuleRes( RB_REF),&aEdRef,_pDlg ),
270 aFtFormResult ( pParent, ModuleRes( FT_FORMULA_RESULT)),
271 aWndFormResult ( pParent, ModuleRes( WND_FORMULA_RESULT)),
272 pTheRefEdit (NULL),
273 pMEdit (NULL),
274 bUserMatrixFlag (sal_False),
275 aTitle1 ( ModuleRes( STR_TITLE1 ) ), // local resource
276 aTitle2 ( ModuleRes( STR_TITLE2 ) ), // local resource
277 aTxtEnd ( ModuleRes( STR_END ) ), // local resource
278 aTxtOk ( aBtnEnd.GetText() ),
279 m_aFormulaHelper(_pFunctionMgr),
280 bIsShutDown (sal_False),
281 nEdFocus (0),
282 pFuncDesc (NULL),
283 nArgs (0)
285 pParaWin = new ParaWin( pParent,_pDlg, aGEdit.GetPosPixel());
286 aGEdit.Hide();
287 pParaWin->Hide();
288 aFtEditName.Hide();
289 aEdRef.Hide();
290 aRefBtn.Hide();
292 pMEdit = aMEFormula.GetEdit();
294 aMEFormula.SetAccessibleName(aFtFormula.GetText());
295 if (pMEdit)
296 pMEdit->SetAccessibleName(aFtFormula.GetText());
298 m_aEditHelpId = pMEdit->GetHelpId();
299 pMEdit->SetUniqueId( m_aEditHelpId );
301 bEditFlag=sal_False;
302 bStructUpdate=sal_True;
303 Point aPos=aGEdit.GetPosPixel();
304 pParaWin->SetPosPixel(aPos);
305 pParaWin->SetArgModifiedHdl(LINK( this, FormulaDlg_Impl, ModifyHdl ) );
306 pParaWin->SetFxHdl(LINK( this, FormulaDlg_Impl, FxHdl ) );
308 pFuncPage= new FuncPage( &aTabCtrl,_pFunctionMgr);
309 pStructPage= new StructPage( &aTabCtrl);
310 pFuncPage->Hide();
311 pStructPage->Hide();
312 aTabCtrl.SetTabPage( TP_FUNCTION, pFuncPage);
313 aTabCtrl.SetTabPage( TP_STRUCT, pStructPage);
315 aOldHelp = pParent->GetHelpId(); // HelpId from resource always for "Page 1"
316 aOldUnique = pParent->GetUniqueId();
318 aFtResult.Show( _bSupportResult );
319 aWndResult.Show( _bSupportResult );
321 aFtFormResult.Show( _bSupportFunctionResult );
322 aWndFormResult.Show( _bSupportFunctionResult );
324 if ( _bSupportMatrix )
325 aBtnMatrix.SetClickHdl(LINK( this, FormulaDlg_Impl, MatrixHdl ) );
326 else
327 aBtnMatrix.Hide();
329 aBtnCancel .SetClickHdl( LINK( this, FormulaDlg_Impl, BtnHdl ) );
330 aBtnEnd .SetClickHdl( LINK( this, FormulaDlg_Impl, BtnHdl ) );
331 aBtnForward .SetClickHdl( LINK( this, FormulaDlg_Impl, BtnHdl ) );
332 aBtnBackward.SetClickHdl( LINK( this, FormulaDlg_Impl, BtnHdl ) );
334 pFuncPage->SetDoubleClickHdl( LINK( this, FormulaDlg_Impl, DblClkHdl ) );
335 pFuncPage->SetSelectHdl( LINK( this, FormulaDlg_Impl, FuncSelHdl) );
336 pStructPage->SetSelectionHdl( LINK( this, FormulaDlg_Impl, StructSelHdl ) );
337 pMEdit->SetModifyHdl( LINK( this, FormulaDlg_Impl, FormulaHdl ) );
338 aMEFormula.SetSelChangedHdl( LINK( this, FormulaDlg_Impl, FormulaCursorHdl ) );
340 aFntLight = aFtFormula.GetFont();
341 aFntLight.SetTransparent( sal_True );
342 aFntBold = aFntLight;
343 aFntBold.SetWeight( WEIGHT_BOLD );
345 pParaWin->SetArgumentFonts(aFntBold,aFntLight);
347 // function description for choosing a function is no longer in a different color
349 aFtHeadLine.SetFont(aFntBold);
350 aFtFuncName.SetFont(aFntLight);
351 aFtFuncDesc.SetFont(aFntLight);
353 FormulaDlg_Impl::~FormulaDlg_Impl()
355 if(aTimer.IsActive())
357 aTimer.SetTimeoutHdl(Link());
358 aTimer.Stop();
359 }// if(aTimer.IsActive())
360 bIsShutDown=sal_True;// Set it in order to PreNotify not to save GetFocus.
362 aTabCtrl.RemovePage(TP_FUNCTION);
363 aTabCtrl.RemovePage(TP_STRUCT);
365 delete pStructPage;
366 delete pFuncPage;
367 delete pParaWin;
368 DeleteArgs();
371 void FormulaDlg_Impl::StoreFormEditData(FormEditData* pData)
373 if (pData) // it won't be destroyed over Close;
375 pData->SetFStart((xub_StrLen)pMEdit->GetSelection().Min());
376 pData->SetSelection(pMEdit->GetSelection());
378 if(aTabCtrl.GetCurPageId()==TP_FUNCTION)
379 pData->SetMode( (sal_uInt16) FORMULA_FORMDLG_FORMULA );
380 else
381 pData->SetMode( (sal_uInt16) FORMULA_FORMDLG_EDIT );
382 pData->SetUndoStr(pMEdit->GetText());
383 pData->SetMatrixFlag(aBtnMatrix.IsChecked());
387 // -----------------------------------------------------------------------------
388 void FormulaDlg_Impl::PreNotify( NotifyEvent& rNEvt )
390 sal_uInt16 nSwitch=rNEvt.GetType();
391 if(nSwitch==EVENT_GETFOCUS && !bIsShutDown)
393 Window* pWin=rNEvt.GetWindow();
394 if(pWin!=NULL)
396 aActivWinId = pWin->GetUniqueId();
397 if(aActivWinId.isEmpty())
399 Window* pParent=pWin->GetParent();
400 while(pParent!=NULL)
402 aActivWinId=pParent->GetUniqueId();
404 if(!aActivWinId.isEmpty()) break;
406 pParent=pParent->GetParent();
409 if(!aActivWinId.isEmpty())
412 FormEditData* pData = m_pHelper->getFormEditData();
414 if (pData && !aTimer.IsActive()) // it won't be destroyed over Close;
416 pData->SetUniqueId(aActivWinId);
422 uno::Reference< sheet::XFormulaOpCodeMapper > FormulaDlg_Impl::GetFormulaOpCodeMapper() const
424 if ( !m_xOpCodeMapper.is() )
426 m_xOpCodeMapper = m_pHelper->getFormulaOpCodeMapper();
427 m_aFunctionOpCodes = m_xOpCodeMapper->getAvailableMappings(sheet::FormulaLanguage::ODFF,sheet::FormulaMapGroup::FUNCTIONS);
428 m_pFunctionOpCodesEnd = m_aFunctionOpCodes.getConstArray() + m_aFunctionOpCodes.getLength();
430 m_aUnaryOpCodes = m_xOpCodeMapper->getAvailableMappings(sheet::FormulaLanguage::ODFF,sheet::FormulaMapGroup::UNARY_OPERATORS);
431 m_pUnaryOpCodesEnd = m_aUnaryOpCodes.getConstArray() + m_aUnaryOpCodes.getLength();
433 m_aBinaryOpCodes = m_xOpCodeMapper->getAvailableMappings(sheet::FormulaLanguage::ODFF,sheet::FormulaMapGroup::BINARY_OPERATORS);
434 m_pBinaryOpCodesEnd = m_aBinaryOpCodes.getConstArray() + m_aBinaryOpCodes.getLength();
436 uno::Sequence< ::rtl::OUString > aArgs(3);
437 aArgs[TOKEN_OPEN] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("("));
438 aArgs[TOKEN_CLOSE] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(")"));
439 aArgs[TOKEN_SEP] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(";"));
440 m_aSeparatorsOpCodes = m_xOpCodeMapper->getMappings(aArgs,sheet::FormulaLanguage::ODFF);
442 m_aSpecialOpCodes = m_xOpCodeMapper->getAvailableMappings(sheet::FormulaLanguage::ODFF,sheet::FormulaMapGroup::SPECIAL);
443 m_pSpecialOpCodesEnd = m_aSpecialOpCodes.getConstArray() + m_aSpecialOpCodes.getLength();
444 } // if ( !m_xOpCodeMapper.is() )
445 return m_xOpCodeMapper;
448 void FormulaDlg_Impl::DeleteArgs()
450 ::std::vector< ::rtl::OUString>().swap(m_aArguments);
451 nArgs = 0;
453 namespace
455 // comparing two property instances
456 struct OpCodeCompare : public ::std::binary_function< sheet::FormulaOpCodeMapEntry, sal_Int32 , bool >
458 bool operator() (const sheet::FormulaOpCodeMapEntry& x, sal_Int32 y) const
460 return x.Token.OpCode == y;
464 // -----------------------------------------------------------------------------
465 xub_StrLen FormulaDlg_Impl::GetFunctionPos(xub_StrLen nPos)
467 const sal_Unicode sep = m_pHelper->getFunctionManager()->getSingleToken(IFunctionManager::eSep);
469 xub_StrLen nFuncPos=STRING_NOTFOUND; //@ Testwise
470 sal_Bool bFlag=sal_False;
471 String aFormString = m_aFormulaHelper.GetCharClass()->uppercase(pMEdit->GetText());
473 if ( m_aTokenList.getLength() )
475 const uno::Reference< sheet::XFormulaParser > xParser(m_pHelper->getFormulaParser());
476 const table::CellAddress aRefPos(m_pHelper->getReferencePosition());
478 const sheet::FormulaToken* pIter = m_aTokenList.getConstArray();
479 const sheet::FormulaToken* pEnd = pIter + m_aTokenList.getLength();
482 xub_StrLen nTokPos=1;
483 xub_StrLen nOldTokPos=1;
484 xub_StrLen nPrevFuncPos = 1;
485 short nBracketCount = 0;
486 while ( pIter != pEnd )
488 const sal_Int32 eOp = pIter->OpCode;
489 uno::Sequence<sheet::FormulaToken> aArgs(1);
490 aArgs[0] = *pIter;
491 const String aString = xParser->printFormula(aArgs, aRefPos);
492 const sheet::FormulaToken* pNextToken = pIter + 1;
494 if(!bUserMatrixFlag && FormulaCompiler::IsMatrixFunction((OpCode)eOp) )
496 aBtnMatrix.Check();
499 if ( eOp == m_aSpecialOpCodes[sheet::FormulaMapGroupSpecialOffset::PUSH].Token.OpCode ||
500 eOp == m_aSpecialOpCodes[sheet::FormulaMapGroupSpecialOffset::SPACES].Token.OpCode )
502 const xub_StrLen n1=aFormString.Search(sep, nTokPos);
503 const xub_StrLen n2=aFormString.Search(')',nTokPos);
504 xub_StrLen nXXX=nTokPos;
505 if(n1<n2)
507 nTokPos=n1;
509 else
511 nTokPos=n2;
513 if ( pNextToken != pEnd )
515 aArgs[0] = *pNextToken;
516 const String a2String = xParser->printFormula(aArgs, aRefPos);
517 const xub_StrLen n3 = aFormString.Search(a2String,nXXX);
518 if ( n3 < nTokPos )
519 nTokPos = n3;
522 else
524 nTokPos = sal::static_int_cast<xub_StrLen>( nTokPos + aString.Len() );
527 if ( eOp == m_aSeparatorsOpCodes[TOKEN_OPEN].OpCode )
529 nBracketCount++;
530 bFlag=sal_True;
532 else if ( eOp == m_aSeparatorsOpCodes[TOKEN_CLOSE].OpCode )
534 nBracketCount--;
535 bFlag=sal_False;
536 nFuncPos=nPrevFuncPos;
538 bool bIsFunction = ::std::find_if(m_aFunctionOpCodes.getConstArray(),m_pFunctionOpCodesEnd,::std::bind2nd(OpCodeCompare(),boost::cref(eOp))) != m_pFunctionOpCodesEnd;
540 if ( bIsFunction && m_aSpecialOpCodes[sheet::FormulaMapGroupSpecialOffset::SPACES].Token.OpCode != eOp )
542 nPrevFuncPos = nFuncPos;
543 nFuncPos = nOldTokPos;
546 if ( nOldTokPos <= nPos && nPos < nTokPos )
548 if ( !bIsFunction )
550 if ( nBracketCount < 1 )
552 nFuncPos= pMEdit->GetText().Len();
554 else if ( !bFlag )
556 nFuncPos=nPrevFuncPos;
559 break;
562 pIter = pNextToken;
563 nOldTokPos = nTokPos;
564 } // while ( pIter != pEnd )
566 catch(const uno::Exception& )
568 OSL_FAIL("Exception caught!");
572 return nFuncPos;
574 // -----------------------------------------------------------------------------
575 sal_Bool FormulaDlg_Impl::CalcValue( const String& rStrExp, String& rStrResult )
577 sal_Bool bResult = sal_True;
579 if ( rStrExp.Len() > 0 )
581 // Only calculate the value when there isn't any more keyboard input:
583 if ( !Application::AnyInput( VCL_INPUT_KEYBOARD ) )
585 bResult = m_pHelper->calculateValue(rStrExp,rStrResult);
587 else
588 bResult = sal_False;
591 return bResult;
594 void FormulaDlg_Impl::UpdateValues()
596 String aStrResult;
598 if ( CalcValue( pFuncDesc->getFormula( m_aArguments ), aStrResult ) )
599 aWndResult.SetValue( aStrResult );
601 aStrResult.Erase();
602 if ( CalcValue(m_pHelper->getCurrentFormula(), aStrResult ) )
603 aWndFormResult.SetValue( aStrResult );
604 else
606 aStrResult.Erase();
607 aWndFormResult.SetValue( aStrResult );
609 CalcStruct(pMEdit->GetText());
612 sal_Bool FormulaDlg_Impl::CalcStruct( const String& rStrExp)
614 sal_Bool bResult = sal_True;
615 xub_StrLen nLength=rStrExp.Len();
617 if ( rStrExp.Len() > 0 && aOldFormula!=rStrExp && bStructUpdate)
619 // Only calculate the value when there isn't any more keyboard input:
621 if ( !Application::AnyInput( VCL_INPUT_KEYBOARD ) )
623 pStructPage->ClearStruct();
625 String aString=rStrExp;
626 if(rStrExp.GetChar(nLength-1)=='(')
628 aString.Erase((xub_StrLen)(nLength-1));
631 aString = comphelper::string::remove(aString, '\n');
632 String aStrResult;
634 if ( CalcValue(aString, aStrResult ) )
635 aWndFormResult.SetValue( aStrResult );
637 UpdateTokenArray(aString);
638 fillTree(pStructPage);
640 aOldFormula=rStrExp;
641 if(rStrExp.GetChar(nLength-1)=='(')
642 UpdateTokenArray(rStrExp);
644 else
645 bResult = sal_False;
647 return bResult;
650 // -----------------------------------------------------------------------------
651 void FormulaDlg_Impl::MakeTree(IStructHelper* _pTree,SvTreeListEntry* pParent,FormulaToken* _pToken,long Count)
653 if( _pToken != NULL && Count > 0 )
655 long nParas = _pToken->GetParamCount();
656 OpCode eOp = _pToken->GetOpCode();
658 // #i101512# for output, the original token is needed
659 FormulaToken* pOrigToken = (_pToken->GetType() == svFAP) ? _pToken->GetFAPOrigToken() : _pToken;
660 uno::Sequence<sheet::FormulaToken> aArgs(1);
661 ::std::map<FormulaToken*,sheet::FormulaToken>::const_iterator itr = m_aTokenMap.find(pOrigToken);
662 if (itr == m_aTokenMap.end())
663 return;
665 aArgs[0] = itr->second;
668 const table::CellAddress aRefPos(m_pHelper->getReferencePosition());
669 const String aResult = m_pHelper->getFormulaParser()->printFormula(aArgs, aRefPos);
671 if ( nParas > 0 )
673 SvTreeListEntry* pEntry;
675 String aTest=_pTree->GetEntryText(pParent);
677 if(aTest==aResult &&
678 (eOp==ocAdd || eOp==ocMul ||
679 eOp==ocAmpersand))
681 pEntry=pParent;
683 else
685 if(eOp==ocBad)
687 pEntry=_pTree->InsertEntry(aResult,pParent,STRUCT_ERROR,0,_pToken);
689 else
691 pEntry=_pTree->InsertEntry(aResult,pParent,STRUCT_FOLDER,0,_pToken);
695 MakeTree(_pTree,pEntry,m_pTokenArray->PrevRPN(),nParas);
696 --Count;
697 m_pTokenArray->NextRPN();
698 MakeTree(_pTree,pParent,m_pTokenArray->PrevRPN(),Count);
700 else
702 if(eOp==ocBad)
704 _pTree->InsertEntry(aResult,pParent,STRUCT_ERROR,0,_pToken);
706 else
708 _pTree->InsertEntry(aResult,pParent,STRUCT_END,0,_pToken);
710 --Count;
711 MakeTree(_pTree,pParent,m_pTokenArray->PrevRPN(),Count);
714 catch(const uno::Exception&)
716 DBG_UNHANDLED_EXCEPTION();
721 void FormulaDlg_Impl::fillTree(IStructHelper* _pTree)
723 GetFormulaOpCodeMapper();
724 FormulaToken* pToken = m_pTokenArray->LastRPN();
726 if( pToken != NULL)
728 MakeTree(_pTree,NULL,pToken,1);
731 void FormulaDlg_Impl::UpdateTokenArray( const String& rStrExp)
733 m_aTokenMap.clear();
734 m_aTokenList.realloc(0);
737 const table::CellAddress aRefPos(m_pHelper->getReferencePosition());
738 m_aTokenList = m_pHelper->getFormulaParser()->parseFormula(rStrExp, aRefPos);
740 catch(const uno::Exception&)
742 DBG_UNHANDLED_EXCEPTION();
744 GetFormulaOpCodeMapper(); // just to get it initialized
745 m_pTokenArray = m_pHelper->convertToTokenArray(m_aTokenList);
746 const sal_Int32 nLen = static_cast<sal_Int32>(m_pTokenArray->GetLen());
747 FormulaToken** pTokens = m_pTokenArray->GetArray();
748 if ( pTokens && nLen == m_aTokenList.getLength() )
750 for (sal_Int32 nPos=0; nPos<nLen; nPos++)
752 m_aTokenMap.insert(::std::map<FormulaToken*,sheet::FormulaToken>::value_type(pTokens[nPos],m_aTokenList[nPos]));
754 } // if ( pTokens && nLen == m_aTokenList.getLength() )
756 FormulaCompiler aCompiler(*m_pTokenArray.get());
757 aCompiler.SetCompileForFAP(sal_True); // #i101512# special handling is needed
758 aCompiler.CompileTokenArray();
761 void FormulaDlg_Impl::FillDialog(sal_Bool nFlag)
763 sal_Bool bNext=sal_True, bPrev=sal_True;
764 if(nFlag)
765 FillControls(bNext, bPrev);
766 FillListboxes();
767 if(nFlag)
769 aBtnBackward.Enable(bPrev);
770 aBtnForward.Enable(bNext);
773 String aStrResult;
775 if ( CalcValue(m_pHelper->getCurrentFormula(), aStrResult ) )
776 aWndFormResult.SetValue( aStrResult );
777 else
779 aStrResult.Erase();
780 aWndFormResult.SetValue( aStrResult );
784 // -----------------------------------------------------------------------------
785 void FormulaDlg_Impl::FillListboxes()
787 // Switch between the "Pages"
788 FormEditData* pData = m_pHelper->getFormEditData();
789 String aNewTitle;
790 // 1. Page: select function
791 if ( pFuncDesc && pFuncDesc->getCategory() )
793 if( pFuncPage->GetCategory() != pFuncDesc->getCategory()->getNumber() + 1 )
794 pFuncPage->SetCategory(static_cast<sal_uInt16>(pFuncDesc->getCategory()->getNumber() + 1));
796 sal_uInt16 nPos=pFuncPage->GetFuncPos(pFuncDesc);
798 pFuncPage->SetFunction(nPos);
800 else if ( pData )
802 pFuncPage->SetCategory( pData->GetCatSel() );
803 pFuncPage->SetFunction( pData->GetFuncSel() );
805 FuncSelHdl(NULL);
807 m_pHelper->setDispatcherLock( sal_True );// Activate Modal-Mode
809 aNewTitle = aTitle1;
811 // HelpId for 1. page is the one from the resource
812 m_pParent->SetHelpId( aOldHelp );
813 m_pParent->SetUniqueId( aOldUnique );
815 // -----------------------------------------------------------------------------
816 void FormulaDlg_Impl::FillControls(sal_Bool &rbNext, sal_Bool &rbPrev)
818 // Switch between the "Pages"
819 FormEditData* pData = m_pHelper->getFormEditData();
820 if (!pData )
821 return;
823 String aNewTitle;
824 // 2. Page or Edit: show selected function
826 xub_StrLen nFStart = pData->GetFStart();
827 String aFormula = m_pHelper->getCurrentFormula();
828 xub_StrLen nNextFStart = nFStart;
829 xub_StrLen nNextFEnd = 0;
831 aFormula.AppendAscii(RTL_CONSTASCII_STRINGPARAM( " )" ));
832 DeleteArgs();
833 const IFunctionDescription* pOldFuncDesc = pFuncDesc;
834 sal_Bool bTestFlag = sal_False;
836 if ( m_aFormulaHelper.GetNextFunc( aFormula, sal_False,
837 nNextFStart, &nNextFEnd, &pFuncDesc, &m_aArguments ) )
839 bTestFlag = (pOldFuncDesc != pFuncDesc);
840 if(bTestFlag)
842 aFtHeadLine.Hide();
843 aFtFuncName.Hide();
844 aFtFuncDesc.Hide();
845 pParaWin->SetFunctionDesc(pFuncDesc);
846 aFtEditName.SetText( pFuncDesc->getFunctionName() );
847 aFtEditName.Show();
848 pParaWin->Show();
849 const rtl::OString aHelpId = pFuncDesc->getHelpId();
850 if ( !aHelpId.isEmpty() )
851 pMEdit->SetHelpId(aHelpId);
854 xub_StrLen nOldStart, nOldEnd;
855 m_pHelper->getSelection( nOldStart, nOldEnd );
856 if ( nOldStart != nNextFStart || nOldEnd != nNextFEnd )
858 m_pHelper->setSelection( nNextFStart, nNextFEnd );
860 aFuncSel.Min() = nNextFStart;
861 aFuncSel.Max() = nNextFEnd;
863 if(!bEditFlag)
864 pMEdit->SetText(m_pHelper->getCurrentFormula());
865 xub_StrLen PrivStart, PrivEnd;
866 m_pHelper->getSelection( PrivStart, PrivEnd);
867 if(!bEditFlag)
868 pMEdit->SetSelection( Selection(PrivStart, PrivEnd));
870 nArgs = pFuncDesc->getSuppressedArgumentCount();
871 sal_uInt16 nOffset = pData->GetOffset();
872 nEdFocus = pData->GetEdFocus();
874 // Concatenate the Edit's for Focus-Control
876 if(bTestFlag)
877 pParaWin->SetArgumentOffset(nOffset);
878 sal_uInt16 nActiv=0;
879 xub_StrLen nArgPos= m_aFormulaHelper.GetArgStart( aFormula, nFStart, 0 );
880 xub_StrLen nEditPos=(xub_StrLen) pMEdit->GetSelection().Min();
881 sal_Bool bFlag=sal_False;
883 for(sal_uInt16 i=0;i<nArgs;i++)
885 sal_Int32 nLength = m_aArguments[i].getLength()+1;
886 pParaWin->SetArgument(i,m_aArguments[i]);
887 if(nArgPos<=nEditPos && nEditPos<nArgPos+nLength)
889 nActiv=i;
890 bFlag=sal_True;
892 nArgPos = sal::static_int_cast<xub_StrLen>( nArgPos + nLength );
894 pParaWin->UpdateParas();
896 if(bFlag)
898 pParaWin->SetActiveLine(nActiv);
901 UpdateValues();
903 else
905 aFtEditName.SetText(String());
906 pMEdit->SetHelpId( m_aEditHelpId );
908 // Test, ob vorne/hinten noch mehr Funktionen sind
910 xub_StrLen nTempStart = m_aFormulaHelper.GetArgStart( aFormula, nFStart, 0 );
911 rbNext = m_aFormulaHelper.GetNextFunc( aFormula, sal_False, nTempStart );
912 nTempStart=(xub_StrLen)pMEdit->GetSelection().Min();
913 pData->SetFStart(nTempStart);
914 rbPrev = m_aFormulaHelper.GetNextFunc( aFormula, sal_True, nTempStart );
916 // -----------------------------------------------------------------------------
918 void FormulaDlg_Impl::ClearAllParas()
920 DeleteArgs();
921 pFuncDesc = NULL;
922 pParaWin->ClearAll();
923 aWndResult.SetValue(String());
924 aFtFuncName.SetText(String());
925 FuncSelHdl(NULL);
927 if(pFuncPage->IsVisible())
929 aFtEditName.Hide();
930 pParaWin->Hide();
932 aBtnForward.Enable(sal_True); //@new
933 aFtHeadLine.Show();
934 aFtFuncName.Show();
935 aFtFuncDesc.Show();
938 String FormulaDlg_Impl::RepairFormula(const String& aFormula)
940 rtl::OUString aResult('=');
943 UpdateTokenArray(aFormula);
945 if ( m_aTokenList.getLength() )
947 const table::CellAddress aRefPos(m_pHelper->getReferencePosition());
948 const String sFormula(m_pHelper->getFormulaParser()->printFormula(m_aTokenList, aRefPos));
949 if ( !sFormula.Len() || sFormula.GetChar(0) != '=' )
950 aResult += sFormula;
951 else
952 aResult = sFormula;
956 catch(const uno::Exception& )
958 OSL_FAIL("Exception caught!");
960 return aResult;
963 void FormulaDlg_Impl::DoEnter(sal_Bool bOk)
965 // Accept input to the document or cancel
966 if ( bOk)
968 // remove dummy arguments
969 String aInputFormula = m_pHelper->getCurrentFormula();
970 String aString = RepairFormula(pMEdit->GetText());
971 m_pHelper->setSelection(0, aInputFormula.Len());
972 m_pHelper->setCurrentFormula(aString);
975 m_pHelper->switchBack();
977 m_pHelper->dispatch(bOk,aBtnMatrix.IsChecked());
978 // Clear data
979 m_pHelper->deleteFormData();
981 // Close dialog
982 m_pHelper->doClose(bOk);
984 // -----------------------------------------------------------------------------
986 IMPL_LINK( FormulaDlg_Impl, BtnHdl, PushButton*, pBtn )
988 if ( pBtn == &aBtnCancel )
990 DoEnter(sal_False); // closes the Dialog
992 else if ( pBtn == &aBtnEnd )
994 DoEnter(sal_True); // closes the Dialog
996 else if ( pBtn == &aBtnForward )
998 const IFunctionDescription* pDesc =pFuncPage->GetFuncDesc( pFuncPage->GetFunction() );
1000 if(pDesc==pFuncDesc || !pFuncPage->IsVisible())
1001 EditNextFunc( sal_True );
1002 else
1004 DblClkHdl(pFuncPage); //new
1005 aBtnForward.Enable(sal_False); //new
1008 else if ( pBtn == &aBtnBackward )
1010 bEditFlag=sal_False;
1011 aBtnForward.Enable(sal_True);
1012 EditNextFunc( sal_False );
1013 aMEFormula.Invalidate();
1014 aMEFormula.Update();
1016 //...
1018 return 0;
1020 // -----------------------------------------------------------------------------
1023 // --------------------------------------------------------------------------
1024 // Functions for 1. Page
1025 // --------------------------------------------------------------------------
1027 // -----------------------------------------------------------------------------
1029 // Handler for Listboxes
1031 IMPL_LINK_NOARG(FormulaDlg_Impl, DblClkHdl)
1033 sal_uInt16 nFunc = pFuncPage->GetFunction();
1035 // ex-UpdateLRUList
1036 const IFunctionDescription* pDesc = pFuncPage->GetFuncDesc(nFunc);
1037 m_pHelper->insertEntryToLRUList(pDesc);
1039 String aFuncName = pFuncPage->GetSelFunctionName();
1040 aFuncName.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "()" ));
1041 m_pHelper->setCurrentFormula(aFuncName);
1042 pMEdit->ReplaceSelected(aFuncName);
1044 Selection aSel=pMEdit->GetSelection();
1045 aSel.Max()=aSel.Max()-1;
1046 pMEdit->SetSelection(aSel);
1048 FormulaHdl(pMEdit);
1050 aSel.Min()=aSel.Max();
1051 pMEdit->SetSelection(aSel);
1053 if(nArgs==0)
1055 BtnHdl(&aBtnBackward);
1058 pParaWin->SetEdFocus(0);
1059 aBtnForward.Enable(sal_False); //@New
1061 return 0;
1063 // -----------------------------------------------------------------------------
1065 // --------------------------------------------------------------------------
1066 // Functions for right Page
1067 // --------------------------------------------------------------------------
1068 void FormulaDlg_Impl::SetData(xub_StrLen nFStart,xub_StrLen nNextFStart,xub_StrLen nNextFEnd,xub_StrLen& PrivStart,xub_StrLen& PrivEnd)
1070 xub_StrLen nFEnd;
1072 // Notice and set new selection
1073 m_pHelper->getSelection( nFStart, nFEnd );
1074 m_pHelper->setSelection( nNextFStart, nNextFEnd );
1075 if(!bEditFlag)
1076 pMEdit->SetText(m_pHelper->getCurrentFormula());
1079 m_pHelper->getSelection( PrivStart, PrivEnd);
1080 if(!bEditFlag)
1082 pMEdit->SetSelection( Selection(PrivStart, PrivEnd));
1083 aMEFormula.UpdateOldSel();
1086 FormEditData* pData = m_pHelper->getFormEditData();
1087 pData->SetFStart( nNextFStart );
1088 pData->SetOffset( 0 );
1089 pData->SetEdFocus( 0 );
1091 FillDialog();
1093 // -----------------------------------------------------------------------------
1094 void FormulaDlg_Impl::EditThisFunc(xub_StrLen nFStart)
1096 FormEditData* pData = m_pHelper->getFormEditData();
1097 if (!pData) return;
1099 String aFormula = m_pHelper->getCurrentFormula();
1101 if(nFStart==NOT_FOUND)
1103 nFStart = pData->GetFStart();
1105 else
1107 pData->SetFStart(nFStart);
1110 xub_StrLen nNextFStart = nFStart;
1111 xub_StrLen nNextFEnd = 0;
1113 sal_Bool bFound;
1115 bFound = m_aFormulaHelper.GetNextFunc( aFormula, sal_False, nNextFStart, &nNextFEnd);
1116 if ( bFound )
1118 xub_StrLen PrivStart, PrivEnd;
1119 SetData(nFStart,nNextFStart,nNextFEnd,PrivStart, PrivEnd);
1120 m_pHelper->showReference(aFormula.Copy(PrivStart, PrivEnd-PrivStart));
1122 else
1124 ClearAllParas();
1128 void FormulaDlg_Impl::EditNextFunc( sal_Bool bForward, xub_StrLen nFStart )
1130 FormEditData* pData = m_pHelper->getFormEditData();
1131 if (!pData)
1132 return;
1134 String aFormula = m_pHelper->getCurrentFormula();
1136 if(nFStart==NOT_FOUND)
1138 nFStart = pData->GetFStart();
1140 else
1142 pData->SetFStart(nFStart);
1145 xub_StrLen nNextFStart = 0;
1146 xub_StrLen nNextFEnd = 0;
1148 sal_Bool bFound;
1149 if ( bForward )
1151 nNextFStart = m_aFormulaHelper.GetArgStart( aFormula, nFStart, 0 );
1152 bFound = m_aFormulaHelper.GetNextFunc( aFormula, sal_False, nNextFStart, &nNextFEnd);
1154 else
1156 nNextFStart = nFStart;
1157 bFound = m_aFormulaHelper.GetNextFunc( aFormula, sal_True, nNextFStart, &nNextFEnd);
1160 if ( bFound )
1162 xub_StrLen PrivStart, PrivEnd;
1163 SetData(nFStart,nNextFStart,nNextFEnd,PrivStart, PrivEnd);
1167 void FormulaDlg_Impl::SaveArg( sal_uInt16 nEd )
1169 if (nEd<nArgs)
1171 sal_uInt16 i;
1172 for(i=0;i<=nEd;i++)
1174 if ( m_aArguments[i].isEmpty() )
1175 m_aArguments[i] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" "));
1177 if(pParaWin->GetArgument(nEd).Len()!=0)
1178 m_aArguments[nEd] = pParaWin->GetArgument(nEd);
1180 sal_uInt16 nClearPos=nEd+1;
1181 for(i=nEd+1;i<nArgs;i++)
1183 if(pParaWin->GetArgument(i).Len()!=0)
1185 nClearPos=i+1;
1189 for(i=nClearPos;i<nArgs;i++)
1191 m_aArguments[i] = ::rtl::OUString();
1196 IMPL_LINK( FormulaDlg_Impl, FxHdl, ParaWin*, pPtr )
1198 if(pPtr==pParaWin)
1200 aBtnForward.Enable(sal_True); //@ In order to be able to input another function.
1201 aTabCtrl.SetCurPageId(TP_FUNCTION);
1203 String aUndoStr = m_pHelper->getCurrentFormula(); // it will be added before a ";"
1204 FormEditData* pData = m_pHelper->getFormEditData();
1205 if (!pData) return 0;
1207 sal_uInt16 nArgNo = pParaWin->GetActiveLine();
1208 nEdFocus=nArgNo;
1210 SaveArg(nArgNo);
1211 UpdateSelection();
1213 xub_StrLen nFormulaStrPos = pData->GetFStart();
1215 String aFormula = m_pHelper->getCurrentFormula();
1216 xub_StrLen n1 = m_aFormulaHelper.GetArgStart( aFormula, nFormulaStrPos, nEdFocus+pData->GetOffset() );
1218 pData->SetEdFocus( nEdFocus );
1219 pData->SaveValues();
1220 pData->SetMode( (sal_uInt16) FORMULA_FORMDLG_FORMULA );
1221 pData->SetFStart( n1 );
1222 pData->SetUndoStr( aUndoStr );
1223 ClearAllParas();
1225 FillDialog(sal_False);
1226 pFuncPage->SetFocus(); //There Parawin is not visible anymore
1228 return 0;
1231 IMPL_LINK( FormulaDlg_Impl, ModifyHdl, ParaWin*, pPtr )
1233 if(pPtr==pParaWin)
1235 SaveArg(pParaWin->GetActiveLine());
1236 UpdateValues();
1238 UpdateSelection();
1239 CalcStruct(pMEdit->GetText());
1241 return 0;
1244 IMPL_LINK_NOARG(FormulaDlg_Impl, FormulaHdl)
1247 FormEditData* pData = m_pHelper->getFormEditData();
1248 if (!pData) return 0;
1250 bEditFlag=sal_True;
1251 String aInputFormula=m_pHelper->getCurrentFormula();
1252 String aString=pMEdit->GetText();
1254 Selection aSel =pMEdit->GetSelection();
1255 xub_StrLen nTest=0;
1257 if(aString.Len()==0) //in case everything was cleared
1259 aString +='=';
1260 pMEdit->SetText(aString);
1261 aSel .Min()=1;
1262 aSel .Max()=1;
1263 pMEdit->SetSelection(aSel);
1265 else if(aString.GetChar(nTest)!='=') //in case it's replaced;
1267 aString.Insert( (sal_Unicode)'=', 0 );
1268 pMEdit->SetText(aString);
1269 aSel .Min()+=1;
1270 aSel .Max()+=1;
1271 pMEdit->SetSelection(aSel);
1275 m_pHelper->setSelection(0, aInputFormula.Len());
1276 m_pHelper->setCurrentFormula(aString);
1277 m_pHelper->setSelection((xub_StrLen)aSel.Min(),(xub_StrLen)aSel.Max());
1279 xub_StrLen nPos=(xub_StrLen)aSel.Min()-1;
1281 String aStrResult;
1283 if ( CalcValue(m_pHelper->getCurrentFormula(), aStrResult ) )
1284 aWndFormResult.SetValue( aStrResult );
1285 else
1287 aStrResult.Erase();
1288 aWndFormResult.SetValue( aStrResult );
1290 CalcStruct(aString);
1292 nPos=GetFunctionPos(nPos);
1294 if(nPos<aSel.Min()-1)
1296 xub_StrLen nPos1=aString.Search('(',nPos);
1297 EditNextFunc( sal_False, nPos1);
1299 else
1301 ClearAllParas();
1304 m_pHelper->setSelection((xub_StrLen)aSel.Min(),(xub_StrLen)aSel.Max());
1305 bEditFlag=sal_False;
1306 return 0;
1309 IMPL_LINK_NOARG(FormulaDlg_Impl, FormulaCursorHdl)
1311 FormEditData* pData = m_pHelper->getFormEditData();
1312 if (!pData) return 0;
1313 xub_StrLen nFStart = pData->GetFStart();
1315 bEditFlag=sal_True;
1317 String aInputFormula=m_pHelper->getCurrentFormula();
1318 String aString=pMEdit->GetText();
1320 Selection aSel =pMEdit->GetSelection();
1321 m_pHelper->setSelection((xub_StrLen)aSel.Min(),(xub_StrLen)aSel.Max());
1323 if(aSel.Min()==0)
1325 aSel.Min()=1;
1326 pMEdit->SetSelection(aSel);
1329 if(aSel.Min()!=aString.Len())
1331 xub_StrLen nPos=(xub_StrLen)aSel.Min();
1333 nFStart=GetFunctionPos(nPos - 1);
1335 if(nFStart<nPos)
1337 xub_StrLen nPos1=m_aFormulaHelper.GetFunctionEnd(aString,nFStart);
1339 if(nPos1>nPos || nPos1==STRING_NOTFOUND)
1341 EditThisFunc(nFStart);
1343 else
1345 xub_StrLen n=nPos;
1346 short nCount=1;
1347 while(n>0)
1349 if(aString.GetChar(n)==')')
1350 nCount++;
1351 else if(aString.GetChar(n)=='(')
1352 nCount--;
1353 if(nCount==0) break;
1354 n--;
1356 if(nCount==0)
1358 nFStart=m_aFormulaHelper.GetFunctionStart(aString,n,sal_True);
1359 EditThisFunc(nFStart);
1361 else
1363 ClearAllParas();
1367 else
1369 ClearAllParas();
1372 m_pHelper->setSelection((xub_StrLen)aSel.Min(),(xub_StrLen)aSel.Max());
1374 bEditFlag=sal_False;
1375 return 0;
1378 void FormulaDlg_Impl::UpdateSelection()
1380 m_pHelper->setSelection((xub_StrLen)aFuncSel.Min(),(xub_StrLen)aFuncSel.Max());
1381 m_pHelper->setCurrentFormula( pFuncDesc->getFormula( m_aArguments ) );
1382 pMEdit->SetText(m_pHelper->getCurrentFormula());
1383 xub_StrLen PrivStart, PrivEnd;
1384 m_pHelper->getSelection( PrivStart, PrivEnd);
1385 aFuncSel.Min()=PrivStart;
1386 aFuncSel.Max()=PrivEnd;
1388 nArgs = pFuncDesc->getSuppressedArgumentCount();
1390 String aFormula=pMEdit->GetText();
1391 sal_Int32 nArgPos=m_aFormulaHelper.GetArgStart( aFormula,PrivStart,0);
1393 sal_uInt16 nPos=pParaWin->GetActiveLine();
1395 for(sal_uInt16 i=0;i<nPos;i++)
1397 nArgPos += (m_aArguments[i].getLength() + 1);
1399 sal_Int32 nLength= m_aArguments[nPos].getLength();
1401 Selection aSel(nArgPos,nArgPos+nLength);
1402 m_pHelper->setSelection((sal_uInt16)nArgPos,(sal_uInt16)(nArgPos+nLength));
1403 pMEdit->SetSelection(aSel);
1404 aMEFormula.UpdateOldSel();
1406 ::std::pair<RefButton*,RefEdit*> FormulaDlg_Impl::RefInputStartBefore( RefEdit* pEdit, RefButton* pButton )
1408 aEdRef.Show();
1409 pTheRefEdit = pEdit;
1410 pTheRefButton = pButton;
1412 if( pTheRefEdit )
1414 aEdRef.SetRefString( pTheRefEdit->GetText() );
1415 aEdRef.SetSelection( pTheRefEdit->GetSelection() );
1416 aEdRef.SetHelpId( pTheRefEdit->GetHelpId() );
1417 aEdRef.SetUniqueId( pTheRefEdit->GetUniqueId() );
1420 aRefBtn.Show( pButton != NULL );
1422 ::std::pair<RefButton*,RefEdit*> aPair;
1423 aPair.first = pButton ? &aRefBtn : NULL;
1424 aPair.second = &aEdRef;
1425 return aPair;
1427 void FormulaDlg_Impl::RefInputStartAfter( RefEdit* /*pEdit*/, RefButton* /*pButton*/ )
1429 aRefBtn.SetEndImage();
1431 if( pTheRefEdit )
1433 String aStr = aTitle2;
1434 aStr += ' ';
1435 aStr += aFtEditName.GetText();
1436 aStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "( " ) );
1437 if( pParaWin->GetActiveLine() > 0 )
1438 aStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "...; " ) );
1439 aStr += pParaWin->GetActiveArgName();
1440 if( pParaWin->GetActiveLine() + 1 < nArgs )
1441 aStr.AppendAscii(RTL_CONSTASCII_STRINGPARAM( "; ..." ));
1442 aStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " )" ) );
1444 m_pParent->SetText( MnemonicGenerator::EraseAllMnemonicChars( aStr ) );
1447 void FormulaDlg_Impl::RefInputDoneAfter( sal_Bool bForced )
1449 aRefBtn.SetStartImage();
1450 if( bForced || !aRefBtn.IsVisible() )
1452 aEdRef.Hide();
1453 aRefBtn.Hide();
1454 if( pTheRefEdit )
1456 pTheRefEdit->SetRefString( aEdRef.GetText() );
1457 pTheRefEdit->GrabFocus();
1459 if( pTheRefButton )
1460 pTheRefButton->SetStartImage();
1462 sal_uInt16 nPrivActiv = pParaWin->GetActiveLine();
1463 pParaWin->SetArgument( nPrivActiv, aEdRef.GetText() );
1464 ModifyHdl( pParaWin );
1465 pTheRefEdit = NULL;
1467 m_pParent->SetText( aTitle1 );
1470 RefEdit* FormulaDlg_Impl::GetCurrRefEdit()
1472 return aEdRef.IsVisible() ? &aEdRef : pParaWin->GetActiveEdit();
1474 void FormulaDlg_Impl::Update()
1476 FormEditData* pData = m_pHelper->getFormEditData();
1477 const String sExpression = pMEdit->GetText();
1478 aOldFormula = String();
1479 UpdateTokenArray(sExpression);
1480 FormulaCursorHdl(&aMEFormula);
1481 CalcStruct(sExpression);
1482 if(pData->GetMode() == FORMULA_FORMDLG_FORMULA)
1483 aTabCtrl.SetCurPageId(TP_FUNCTION);
1484 else
1485 aTabCtrl.SetCurPageId(TP_STRUCT);
1486 aBtnMatrix.Check(pData->GetMatrixFlag());
1488 void FormulaDlg_Impl::Update(const String& _sExp)
1490 CalcStruct(_sExp);
1491 FillDialog();
1492 FuncSelHdl(NULL);
1494 void FormulaDlg_Impl::SetMeText(const String& _sText)
1496 FormEditData* pData = m_pHelper->getFormEditData();
1497 pMEdit->SetText(_sText);
1498 pMEdit->SetSelection( pData->GetSelection());
1499 aMEFormula.UpdateOldSel();
1501 FormulaDlgMode FormulaDlg_Impl::SetMeText(const String& _sText,xub_StrLen PrivStart, xub_StrLen PrivEnd,sal_Bool bMatrix,sal_Bool _bSelect,sal_Bool _bUpdate)
1503 FormulaDlgMode eMode = FORMULA_FORMDLG_FORMULA;
1504 if(!bEditFlag)
1505 pMEdit->SetText(_sText);
1507 if ( _bSelect || !bEditFlag )
1508 pMEdit->SetSelection( Selection(PrivStart, PrivEnd));
1509 if ( _bUpdate )
1511 aMEFormula.UpdateOldSel();
1512 pMEdit->Invalidate();
1513 m_pHelper->showReference(pMEdit->GetSelected());
1514 eMode = FORMULA_FORMDLG_EDIT;
1516 aBtnMatrix.Check( bMatrix );
1517 } // if ( _bUpdate )
1518 return eMode;
1520 sal_Bool FormulaDlg_Impl::CheckMatrix(String& aFormula)
1522 pMEdit->GrabFocus();
1523 xub_StrLen nLen = aFormula.Len();
1524 sal_Bool bMatrix = nLen > 3 // Matrix-Formula
1525 && aFormula.GetChar(0) == '{'
1526 && aFormula.GetChar(1) == '='
1527 && aFormula.GetChar(nLen-1) == '}';
1528 if ( bMatrix )
1530 aFormula.Erase( 0, 1 );
1531 aFormula.Erase( aFormula.Len()-1, 1);
1532 aBtnMatrix.Check( bMatrix );
1533 aBtnMatrix.Disable();
1534 } // if ( bMatrix )
1536 aTabCtrl.SetCurPageId(TP_STRUCT);
1537 return bMatrix;
1539 IMPL_LINK_NOARG(FormulaDlg_Impl, StructSelHdl)
1541 bStructUpdate=sal_False;
1542 if(pStructPage->IsVisible()) aBtnForward.Enable(sal_False); //@New
1544 bStructUpdate=sal_True;
1545 return 0;
1547 IMPL_LINK_NOARG(FormulaDlg_Impl, MatrixHdl)
1549 bUserMatrixFlag=sal_True;
1550 return 0;
1553 IMPL_LINK_NOARG(FormulaDlg_Impl, FuncSelHdl)
1555 sal_uInt16 nCat = pFuncPage->GetCategory();
1556 if ( nCat == LISTBOX_ENTRY_NOTFOUND ) nCat = 0;
1557 sal_uInt16 nFunc = pFuncPage->GetFunction();
1558 if ( nFunc == LISTBOX_ENTRY_NOTFOUND ) nFunc = 0;
1560 if ( (pFuncPage->GetFunctionEntryCount() > 0)
1561 && (pFuncPage->GetFunction() != LISTBOX_ENTRY_NOTFOUND) )
1563 const IFunctionDescription* pDesc =pFuncPage->GetFuncDesc( pFuncPage->GetFunction() );
1565 if(pDesc!=pFuncDesc) aBtnForward.Enable(sal_True); //new
1567 if (pDesc)
1569 pDesc->initArgumentInfo(); // full argument info is needed
1571 String aSig = pDesc->getSignature();
1572 aFtHeadLine.SetText( pDesc->getFunctionName() );
1573 aFtFuncName.SetText( aSig );
1574 aFtFuncDesc.SetText( pDesc->getDescription() );
1577 else
1579 aFtHeadLine.SetText( String() );
1580 aFtFuncName.SetText( String() );
1581 aFtFuncDesc.SetText( String() );
1583 return 0;
1586 void FormulaDlg_Impl::UpdateParaWin(const Selection& _rSelection,const String& _sRefStr)
1588 Selection theSel = _rSelection;
1589 aEdRef.ReplaceSelected( _sRefStr );
1590 theSel.Max() = theSel.Min() + _sRefStr.Len();
1591 aEdRef.SetSelection( theSel );
1593 //-------------------------------------
1594 // Manual Update of the results' fields:
1595 //-------------------------------------
1596 sal_uInt16 nPrivActiv = pParaWin->GetActiveLine();
1597 pParaWin->SetArgument(nPrivActiv,aEdRef.GetText());
1598 pParaWin->UpdateParas();
1600 Edit* pEd = GetCurrRefEdit();
1601 if( pEd != NULL )
1602 pEd->SetSelection( theSel );
1604 pParaWin->SetRefMode(sal_False);
1606 sal_Bool FormulaDlg_Impl::UpdateParaWin(Selection& _rSelection)
1608 pParaWin->SetRefMode(sal_True);
1610 String aStrEd;
1611 Edit* pEd = GetCurrRefEdit();
1612 if(pEd!=NULL && pTheRefEdit==NULL)
1614 _rSelection=pEd->GetSelection();
1615 _rSelection.Justify();
1616 aStrEd=pEd->GetText();
1617 aEdRef.SetRefString(aStrEd);
1618 aEdRef.SetSelection( _rSelection );
1620 else
1622 _rSelection=aEdRef.GetSelection();
1623 _rSelection.Justify();
1624 aStrEd= aEdRef.GetText();
1626 return pTheRefEdit == NULL;
1629 void FormulaDlg_Impl::SetEdSelection()
1631 Edit* pEd = GetCurrRefEdit()/*aScParaWin.GetActiveEdit()*/;
1632 if( pEd )
1634 Selection theSel = aEdRef.GetSelection();
1635 // Edit may have the focus -> call ModifyHdl in addition
1636 // to what's happening in GetFocus
1637 pEd->GetModifyHdl().Call(pEd);
1638 pEd->GrabFocus();
1639 pEd->SetSelection(theSel);
1640 } // if( pEd )
1642 // -----------------------------------------------------------------------------
1643 const FormulaHelper& FormulaDlg_Impl::GetFormulaHelper() const
1645 return m_aFormulaHelper;
1647 //============================================================================
1648 FormulaModalDialog::FormulaModalDialog( Window* pParent
1649 , bool _bSupportFunctionResult
1650 , bool _bSupportResult
1651 , bool _bSupportMatrix
1652 , IFunctionManager* _pFunctionMgr
1653 , IControlReferenceHandler* _pDlg ) :
1654 ModalDialog( pParent, ModuleRes(RID_FORMULADLG_FORMULA_MODAL) ),
1655 m_pImpl( new FormulaDlg_Impl(this,_bSupportFunctionResult
1656 , _bSupportResult
1657 , _bSupportMatrix
1658 ,this,_pFunctionMgr,_pDlg))
1660 FreeResource();
1661 SetText(m_pImpl->aTitle1);
1663 FormulaModalDialog::~FormulaModalDialog()
1666 // -----------------------------------------------------------------------------
1667 void FormulaModalDialog::Update(const String& _sExp)
1669 m_pImpl->Update(_sExp);
1672 // -----------------------------------------------------------------------------
1673 void FormulaModalDialog::SetMeText(const String& _sText)
1675 m_pImpl->SetMeText(_sText);
1678 // -----------------------------------------------------------------------------
1679 sal_Bool FormulaModalDialog::CheckMatrix(String& aFormula)
1681 return m_pImpl->CheckMatrix(aFormula);
1683 // -----------------------------------------------------------------------------
1684 void FormulaModalDialog::Update()
1686 m_pImpl->Update();
1688 ::std::pair<RefButton*,RefEdit*> FormulaModalDialog::RefInputStartBefore( RefEdit* pEdit, RefButton* pButton )
1690 return m_pImpl->RefInputStartBefore( pEdit, pButton );
1692 void FormulaModalDialog::RefInputStartAfter( RefEdit* pEdit, RefButton* pButton )
1694 m_pImpl->RefInputStartAfter( pEdit, pButton );
1696 void FormulaModalDialog::RefInputDoneAfter( sal_Bool bForced )
1698 m_pImpl->RefInputDoneAfter( bForced );
1701 void FormulaModalDialog::SetFocusWin(Window *pWin,const rtl::OString& nUniqueId)
1703 if(pWin->GetUniqueId()==nUniqueId)
1705 pWin->GrabFocus();
1707 else
1709 sal_uInt16 nCount=pWin->GetChildCount();
1711 for(sal_uInt16 i=0;i<nCount;i++)
1713 Window* pChild=pWin->GetChild(i);
1714 SetFocusWin(pChild,nUniqueId);
1719 long FormulaModalDialog::PreNotify( NotifyEvent& rNEvt )
1721 m_pImpl->PreNotify( rNEvt );
1723 return ModalDialog::PreNotify(rNEvt);
1726 void FormulaModalDialog::StoreFormEditData(FormEditData* pData)
1728 m_pImpl->StoreFormEditData(pData);
1731 // --------------------------------------------------------------------------
1732 // Initialisation / General functions for Dialog
1733 // --------------------------------------------------------------------------
1734 FormulaDlg::FormulaDlg( SfxBindings* pB, SfxChildWindow* pCW,
1735 Window* pParent
1736 , bool _bSupportFunctionResult
1737 , bool _bSupportResult
1738 , bool _bSupportMatrix
1739 , IFunctionManager* _pFunctionMgr, IControlReferenceHandler* _pDlg ) :
1740 SfxModelessDialog( pB, pCW, pParent, ModuleRes(RID_FORMULADLG_FORMULA) ),
1741 m_pImpl( new FormulaDlg_Impl(this, _bSupportFunctionResult
1742 , _bSupportResult
1743 , _bSupportMatrix
1744 , this, _pFunctionMgr, _pDlg))
1746 FreeResource();
1747 if(GetHelpId().isEmpty()) //Hack which hides the HelpId for a model Dialog in SfxModelessDialog
1748 SetHelpId(GetUniqueId()); //and will be changed in a UniqueId,
1749 //at this point we reverse it.
1750 SetText(m_pImpl->aTitle1);
1753 FormulaDlg::~FormulaDlg()
1756 // -----------------------------------------------------------------------------
1757 void FormulaDlg::Update(const String& _sExp)
1759 m_pImpl->Update(_sExp);
1762 // -----------------------------------------------------------------------------
1763 void FormulaDlg::SetMeText(const String& _sText)
1765 m_pImpl->SetMeText(_sText);
1768 // -----------------------------------------------------------------------------
1769 FormulaDlgMode FormulaDlg::SetMeText(const String& _sText,xub_StrLen PrivStart, xub_StrLen PrivEnd,sal_Bool bMatrix,sal_Bool _bSelect,sal_Bool _bUpdate)
1771 return m_pImpl->SetMeText(_sText,PrivStart, PrivEnd,bMatrix,_bSelect,_bUpdate);
1773 // -----------------------------------------------------------------------------
1774 void FormulaDlg::CheckMatrix()
1776 m_pImpl->aBtnMatrix.Check();
1778 // -----------------------------------------------------------------------------
1779 sal_Bool FormulaDlg::CheckMatrix(String& aFormula)
1781 return m_pImpl->CheckMatrix(aFormula);
1783 // -----------------------------------------------------------------------------
1784 String FormulaDlg::GetMeText() const
1786 return m_pImpl->pMEdit->GetText();
1788 // -----------------------------------------------------------------------------
1789 void FormulaDlg::Update()
1791 m_pImpl->Update();
1792 m_pImpl->aTimer.SetTimeout(200);
1793 m_pImpl->aTimer.SetTimeoutHdl(LINK( this, FormulaDlg, UpdateFocusHdl));
1794 m_pImpl->aTimer.Start();
1797 // -----------------------------------------------------------------------------
1798 sal_Bool FormulaDlg::isUserMatrix() const
1800 return m_pImpl->bUserMatrixFlag;
1802 void FormulaDlg::DoEnter(sal_Bool _bOk)
1804 m_pImpl->DoEnter(_bOk);
1806 ::std::pair<RefButton*,RefEdit*> FormulaDlg::RefInputStartBefore( RefEdit* pEdit, RefButton* pButton )
1808 return m_pImpl->RefInputStartBefore( pEdit, pButton );
1810 void FormulaDlg::RefInputStartAfter( RefEdit* pEdit, RefButton* pButton )
1812 m_pImpl->RefInputStartAfter( pEdit, pButton );
1814 void FormulaDlg::RefInputDoneAfter( sal_Bool bForced )
1816 m_pImpl->RefInputDoneAfter( bForced );
1819 void FormulaDlg::SetFocusWin(Window *pWin,const rtl::OString& nUniqueId)
1821 if(pWin->GetUniqueId()==nUniqueId)
1823 pWin->GrabFocus();
1825 else
1827 sal_uInt16 nCount=pWin->GetChildCount();
1829 for(sal_uInt16 i=0;i<nCount;i++)
1831 Window* pChild=pWin->GetChild(i);
1832 SetFocusWin(pChild,nUniqueId);
1838 long FormulaDlg::PreNotify( NotifyEvent& rNEvt )
1840 m_pImpl->PreNotify( rNEvt );
1841 return SfxModelessDialog::PreNotify(rNEvt);
1844 void FormulaDlg::disableOk()
1846 m_pImpl->aBtnEnd.Disable();
1849 void FormulaDlg::StoreFormEditData(FormEditData* pData)
1851 m_pImpl->StoreFormEditData(pData);
1854 // -----------------------------------------------------------------------------
1855 const IFunctionDescription* FormulaDlg::getCurrentFunctionDescription() const
1857 OSL_VERIFY(!m_pImpl->pFuncDesc || m_pImpl->pFuncDesc->getSuppressedArgumentCount() == m_pImpl->nArgs);
1858 return m_pImpl->pFuncDesc;
1860 // -----------------------------------------------------------------------------
1861 void FormulaDlg::UpdateParaWin(const Selection& _rSelection,const String& _sRefStr)
1863 m_pImpl->UpdateParaWin(_rSelection,_sRefStr);
1865 sal_Bool FormulaDlg::UpdateParaWin(Selection& _rSelection)
1867 return m_pImpl->UpdateParaWin(_rSelection);
1869 // -----------------------------------------------------------------------------
1870 RefEdit* FormulaDlg::GetActiveEdit()
1872 return m_pImpl->pParaWin->GetActiveEdit();
1874 // -----------------------------------------------------------------------------
1875 const FormulaHelper& FormulaDlg::GetFormulaHelper() const
1877 return m_pImpl->GetFormulaHelper();
1879 // -----------------------------------------------------------------------------
1880 void FormulaDlg::SetEdSelection()
1882 m_pImpl->SetEdSelection();
1884 IMPL_LINK_NOARG(FormulaDlg, UpdateFocusHdl)
1886 FormEditData* pData = m_pImpl->m_pHelper->getFormEditData();
1888 if (pData) // won't be destroyed over Close;
1890 m_pImpl->m_pHelper->setReferenceInput(pData);
1891 rtl::OString nUniqueId(pData->GetUniqueId());
1892 SetFocusWin(this,nUniqueId);
1894 return 0;
1897 // -----------------------------------------------------------------------------
1898 void FormEditData::SaveValues()
1900 FormEditData* pTemp = new FormEditData(*this);
1902 Reset();
1903 pParent = pTemp;
1905 // -----------------------------------------------------------------------------
1906 void FormEditData::Reset()
1908 pParent = NULL;
1909 nMode = 0;
1910 nFStart = 0;
1911 nCatSel = 1; //! oder 0 (zuletzt benutzte)
1912 nFuncSel = 0;
1913 nOffset = 0;
1914 nEdFocus = 0;
1915 bMatrix =sal_False;
1916 aUniqueId=rtl::OString();
1917 aSelection.Min()=0;
1918 aSelection.Max()=0;
1919 aUndoStr.Erase();
1921 // -----------------------------------------------------------------------------
1922 const FormEditData& FormEditData::operator=( const FormEditData& r )
1924 pParent = r.pParent;
1925 nMode = r.nMode;
1926 nFStart = r.nFStart;
1927 nCatSel = r.nCatSel;
1928 nFuncSel = r.nFuncSel;
1929 nOffset = r.nOffset;
1930 nEdFocus = r.nEdFocus;
1931 aUndoStr = r.aUndoStr;
1932 bMatrix = r.bMatrix ;
1933 aUniqueId = r.aUniqueId;
1934 aSelection = r.aSelection;
1935 return *this;
1937 // -----------------------------------------------------------------------------
1938 FormEditData::FormEditData()
1940 Reset();
1943 FormEditData::~FormEditData()
1945 delete pParent;
1948 FormEditData::FormEditData( const FormEditData& r )
1950 *this = r;
1953 // -----------------------------------------------------------------------------
1954 } // formula
1955 // -----------------------------------------------------------------------------
1957 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */