update dev300-m57
[ooovba.git] / applied_patches / 0380-calc-vba-volatile-user-func.diff
blob685b6d9a070457bc2ac5affcee0137a52c06e13f
1 diff --git formula/inc/formula/FormulaCompiler.hxx formula/inc/formula/FormulaCompiler.hxx
2 index d5c3410..a388926 100644
3 --- formula/inc/formula/FormulaCompiler.hxx
4 +++ formula/inc/formula/FormulaCompiler.hxx
5 @@ -219,6 +219,8 @@ public:
6 */
7 OpCode GetEnglishOpCode( const String& rName ) const;
9 + static bool IsOpCodeVolatile( OpCode eOp );
11 static BOOL DeQuote( String& rStr );
13 static const String& GetNativeSymbol( OpCode eOp );
14 diff --git formula/source/core/api/FormulaCompiler.cxx formula/source/core/api/FormulaCompiler.cxx
15 index a0a1c1a..72e6409 100644
16 --- formula/source/core/api/FormulaCompiler.cxx
17 +++ formula/source/core/api/FormulaCompiler.cxx
18 @@ -744,6 +744,30 @@ OpCode FormulaCompiler::GetEnglishOpCode( const String& rName ) const
19 return bFound ? (*iLook).second : OpCode(ocNone);
22 +bool FormulaCompiler::IsOpCodeVolatile( OpCode eOp )
24 + switch (eOp)
25 + {
26 + // no parameters:
27 + case ocRandom:
28 + case ocGetActDate:
29 + case ocGetActTime:
30 + // one parameter:
31 + case ocFormula:
32 + case ocInfo:
33 + // more than one parameters:
34 + // ocIndirect/ocIndirectXL otherwise would have to do
35 + // StopListening and StartListening on a reference for every
36 + // interpreted value.
37 + case ocIndirect:
38 + case ocIndirectXL:
39 + // ocOffset results in indirect references.
40 + case ocOffset:
41 + return true;
42 + }
43 + return false;
46 // Remove quotes, escaped quotes are unescaped.
47 BOOL FormulaCompiler::DeQuote( String& rStr )
49 @@ -960,44 +984,32 @@ void FormulaCompiler::Factor()
51 if( nNumFmt == NUMBERFORMAT_UNDEFINED )
52 nNumFmt = lcl_GetRetFormat( eOp );
53 - // Functions that have to be always recalculated
54 - switch( eOp )
56 + if ( IsOpCodeVolatile(eOp) )
57 + pArr->SetRecalcModeAlways();
58 + else
60 - // no parameters:
61 - case ocRandom:
62 - case ocGetActDate:
63 - case ocGetActTime:
64 - // one parameter:
65 - case ocFormula:
66 - case ocInfo:
67 - // more than one parameters:
68 - // ocIndirect/ocIndirectXL otherwise would have to do
69 - // StopListening and StartListening on a reference for every
70 - // interpreted value.
71 - case ocIndirect:
72 - case ocIndirectXL:
73 - // ocOffset results in indirect references.
74 - case ocOffset:
75 - pArr->SetRecalcModeAlways();
76 - break;
77 - // Functions recalculated on every document load.
78 - // Don't use SetRecalcModeOnLoad() which would override
79 - // ModeAlways.
80 - case ocConvert :
81 - pArr->AddRecalcMode( RECALCMODE_ONLOAD );
82 - break;
83 - // If the referred cell is moved the value changes.
84 - case ocColumn :
85 - case ocRow :
86 - // ocCell needs recalc on move for some possible type values.
87 - case ocCell :
88 - pArr->SetRecalcModeOnRefMove();
89 - break;
90 - case ocHyperLink :
91 - pArr->SetHyperLink(TRUE);
92 - break;
93 - default:
94 - ; // nothing
95 + switch( eOp )
96 + {
97 + // Functions recalculated on every document load.
98 + // Don't use SetRecalcModeOnLoad() which would override
99 + // ModeAlways.
100 + case ocConvert :
101 + pArr->AddRecalcMode( RECALCMODE_ONLOAD );
102 + break;
103 + // If the referred cell is moved the value changes.
104 + case ocColumn :
105 + case ocRow :
106 + // ocCell needs recalc on move for some possible type values.
107 + case ocCell :
108 + pArr->SetRecalcModeOnRefMove();
109 + break;
110 + case ocHyperLink :
111 + pArr->SetHyperLink(TRUE);
112 + break;
113 + default:
114 + ; // nothing
117 if (SC_OPCODE_START_NO_PAR <= eOp && eOp < SC_OPCODE_STOP_NO_PAR)
119 --- sc/inc/document.hxx
120 +++ sc/inc/document.hxx
121 @@ -96,6 +96,7 @@ class ScDrawLayer;
122 class ScExtDocOptions;
123 class ScExternalRefManager;
124 class ScFormulaCell;
125 +class ScMacroManager;
126 class ScMarkData;
127 class ScOutlineTable;
128 class ScPatternAttr;
129 @@ -294,6 +295,8 @@ private:
130 ::std::auto_ptr<ScClipParam> mpClipParam;
132 ::std::auto_ptr<ScExternalRefManager> pExternalRefMgr;
133 + ::std::auto_ptr<ScMacroManager> mpMacroMgr;
136 // mutable for lazy construction
137 mutable ::std::auto_ptr< ScFormulaParserPool >
138 @@ -1510,6 +1513,7 @@ public:
139 SC_DLLPUBLIC ScLkUpdMode GetLinkMode() const { return eLinkMode ;}
140 void SetLinkMode( ScLkUpdMode nSet ) { eLinkMode = nSet;}
142 + SC_DLLPUBLIC ScMacroManager* GetMacroManager();
144 private:
145 ScDocument(const ScDocument& r); // disabled with no definition
146 diff --git sc/inc/macromgr.hxx sc/inc/macromgr.hxx
147 new file mode 100644
148 index 0000000..35a3b2d
149 --- /dev/null
150 +++ sc/inc/macromgr.hxx
151 @@ -0,0 +1,70 @@
152 +/*************************************************************************
154 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
156 + * Copyright 2008 by Sun Microsystems, Inc.
158 + * OpenOffice.org - a multi-platform office productivity suite
160 + * $RCSfile: document.hxx,v $
161 + * $Revision: 1.115.36.9 $
163 + * This file is part of OpenOffice.org.
165 + * OpenOffice.org is free software: you can redistribute it and/or modify
166 + * it under the terms of the GNU Lesser General Public License version 3
167 + * only, as published by the Free Software Foundation.
169 + * OpenOffice.org is distributed in the hope that it will be useful,
170 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
171 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
172 + * GNU Lesser General Public License version 3 for more details
173 + * (a copy is included in the LICENSE file that accompanied this code).
175 + * You should have received a copy of the GNU Lesser General Public License
176 + * version 3 along with OpenOffice.org. If not, see
177 + * <http://www.openoffice.org/license.html>
178 + * for a copy of the LGPLv3 License.
180 + ************************************************************************/
182 +#ifndef SC_MACROMGR_HXX
183 +#define SC_MACROMGR_HXX
185 +#include <com/sun/star/container/XContainerListener.hpp>
187 +#include "rtl/ustring.hxx"
188 +#include "scdllapi.h"
190 +#include <hash_map>
191 +#include <memory>
193 +class ScDocument;
194 +class ScFormulaCell;
195 +class ScUserMacroDepTracker;
197 +class ScMacroManager
199 +public:
200 + explicit ScMacroManager(ScDocument* pDoc);
201 + ~ScMacroManager();
203 + SC_DLLPUBLIC void InitUserFuncData();
204 + SC_DLLPUBLIC void SetUserFuncVolatile( const rtl::OUString& sName, bool isVolatile );
205 + SC_DLLPUBLIC bool GetUserFuncVolatile( const rtl::OUString& sName );
207 + void AddDependentCell(const ::rtl::OUString& aModuleName, ScFormulaCell* pCell);
208 + void RemoveDependentCell(ScFormulaCell* pCell);
209 + void BroadcastModuleUpdate(const ::rtl::OUString& aModuleName);
211 +private:
212 + typedef std::hash_map< ::rtl::OUString, bool, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > NameBoolMap;
213 + NameBoolMap mhFuncToVolatile;
214 + com::sun::star::uno::Reference< com::sun::star::container::XContainerListener > mxContainerListener;
216 + ::std::auto_ptr<ScUserMacroDepTracker> mpDepTracker;
217 + ScDocument* mpDoc;
220 +#endif
222 --- sc/source/core/data/cell.cxx
223 +++ sc/source/core/data/cell.cxx
224 @@ -54,6 +54,7 @@
225 #include "recursionhelper.hxx"
226 #include "postit.hxx"
227 #include "externalrefmgr.hxx"
228 +#include "macromgr.hxx"
229 #include <svx/editobj.hxx>
230 #include <svtools/intitem.hxx>
231 #include <svx/flditem.hxx>
232 @@ -855,6 +856,9 @@ ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, cons
233 ScFormulaCell::~ScFormulaCell()
235 pDocument->RemoveFromFormulaTree( this );
236 + if (pCode->HasOpCode(ocMacro))
237 + pDocument->GetMacroManager()->RemoveDependentCell(this);
239 delete pCode;
240 #ifdef DBG_UTIL
241 eCellType = CELLTYPE_DESTROYED;
242 @@ -1721,6 +1725,36 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam )
243 // Reschedule verlangsamt das ganze erheblich, nur bei Prozentaenderung ausfuehren
244 ScProgress::GetInterpretProgress()->SetStateCountDownOnPercent(
245 pDocument->GetFormulaCodeInTree()/MIN_NO_CODES_PER_PROGRESS_UPDATE );
247 + switch (p->GetVolatileType())
249 + case ScInterpreter::VOLATILE:
250 + // Volatile via built-in volatile functions. No actions needed.
251 + break;
252 + case ScInterpreter::VOLATILE_MACRO:
253 + // The formula contains a volatile macro.
254 + pCode->SetRecalcModeAlways();
255 + pDocument->PutInFormulaTree(this);
256 + StartListeningTo(pDocument);
257 + break;
258 + case ScInterpreter::NOT_VOLATILE:
259 + if (pCode->IsRecalcModeAlways())
261 + // The formula was previously volatile, but no more.
262 + EndListeningTo(pDocument);
263 + pCode->SetRecalcModeNormal();
265 + else
266 + {
267 + // non-volatile formula. End listening to the area in case
268 + // it's listening due to macro module change.
269 + pDocument->EndListeningArea(BCA_LISTEN_ALWAYS, this);
271 + pDocument->RemoveFromFormulaTree(this);
272 + break;
273 + default:
277 else
279 --- sc/source/core/data/documen2.cxx
280 +++ sc/source/core/data/documen2.cxx
281 @@ -96,6 +96,7 @@
282 #include "externalrefmgr.hxx"
283 #include "tabprotection.hxx"
284 #include "clipparam.hxx"
285 +#include "macromgr.hxx"
286 #include <com/sun/star/document/XVbaEventsHelper.hpp>
287 #include "formulaparserpool.hxx"
289 @@ -157,6 +158,7 @@ ScDocument::ScDocument( ScDocumentMode eMode,
290 pCacheFieldEditEngine( NULL ),
291 pDocProtection( NULL ),
292 mpClipParam( NULL ),
293 + mpMacroMgr( NULL ),
294 pViewOptions( NULL ),
295 pDocOptions( NULL ),
296 pExtDocOptions( NULL ),
297 diff --git sc/source/core/data/documen8.cxx sc/source/core/data/documen8.cxx
298 index 077b6fa..f1b608c 100644
299 --- sc/source/core/data/documen8.cxx
300 +++ sc/source/core/data/documen8.cxx
301 @@ -96,6 +96,7 @@
302 #include "globstr.hrc"
303 #include "sc.hrc"
304 #include "charthelper.hxx"
305 +#include "macromgr.hxx"
307 #define GET_SCALEVALUE(set,id) ((const SfxUInt16Item&)(set.Get( id ))).GetValue()
309 @@ -427,6 +428,13 @@ BYTE ScDocument::GetEditTextDirection(SCTAB nTab) const
310 return sal::static_int_cast<BYTE>(eRet);
313 +ScMacroManager* ScDocument::GetMacroManager()
315 + if (!mpMacroMgr.get())
316 + mpMacroMgr.reset(new ScMacroManager(this));
317 + return mpMacroMgr.get();
320 //------------------------------------------------------------------------
322 void ScDocument::InvalidateTextWidth( const ScAddress* pAdrFrom, const ScAddress* pAdrTo,
323 diff --git sc/source/core/data/document.cxx sc/source/core/data/document.cxx
324 index 11af993..676883e 100644
325 --- sc/source/core/data/document.cxx
326 +++ sc/source/core/data/document.cxx
327 @@ -95,9 +95,13 @@
328 #include "externalrefmgr.hxx"
329 #include "tabprotection.hxx"
330 #include "clipparam.hxx"
331 +#include <basic/basmgr.hxx>
332 +#include <com/sun/star/container/XContainer.hpp>
334 #include <map>
336 +using namespace ::com::sun::star;
338 namespace WritingMode2 = ::com::sun::star::text::WritingMode2;
340 struct ScDefaultAttr
341 diff --git sc/source/core/inc/interpre.hxx sc/source/core/inc/interpre.hxx
342 index a72775d..3a45be6 100644
343 --- sc/source/core/inc/interpre.hxx
344 +++ sc/source/core/inc/interpre.hxx
345 @@ -128,6 +128,15 @@ public:
346 static inline double div( const double& fNumerator, const double& fDenominator );
348 ScMatrixRef GetNewMat(SCSIZE nC, SCSIZE nR);
350 + enum VolatileType {
351 + VOLATILE,
352 + VOLATILE_MACRO,
353 + NOT_VOLATILE
354 + };
356 + VolatileType GetVolatileType() const;
358 private:
359 static ScTokenStack* pGlobalStack;
360 static BOOL bGlobalStackInUse;
361 @@ -161,6 +170,8 @@ private:
362 BOOL bCalcAsShown; // precision as shown
363 BOOL bMatrixFormula; // formula cell is a matrix formula
365 + VolatileType meVolaileType;
367 //---------------------------------Funktionen in interpre.cxx---------
368 // nMust <= nAct <= nMax ? ok : PushError
369 inline BOOL MustHaveParamCount( short nAct, short nMust );
370 diff --git sc/source/core/tool/interpr4.cxx sc/source/core/tool/interpr4.cxx
371 index baa5152..7fccd66 100644
372 --- sc/source/core/tool/interpr4.cxx
373 +++ sc/source/core/tool/interpr4.cxx
374 @@ -41,6 +41,7 @@
375 #include <basic/sbmod.hxx>
376 #include <basic/sbstar.hxx>
377 #include <basic/sbx.hxx>
378 +#include <basic/sbxobj.hxx>
379 #include <basic/sbuno.hxx>
380 #include <svtools/zforlist.hxx>
381 #include <tools/urlobj.hxx>
382 @@ -71,6 +72,8 @@
383 #include "jumpmatrix.hxx"
384 #include "parclass.hxx"
385 #include "externalrefmgr.hxx"
386 +#include "formula/FormulaCompiler.hxx"
387 +#include "macromgr.hxx"
389 #include <math.h>
390 #include <float.h>
391 @@ -78,6 +81,7 @@
392 #include <algorithm>
393 #include <functional>
394 #include <vbahelper/vbahelper.hxx>
395 +#include <basic/basmgr.hxx>
397 using namespace com::sun::star;
398 using namespace formula;
399 @@ -2751,7 +2755,9 @@ void ScInterpreter::ScMacro()
400 return;
403 + bool bVolatileMacro = false;
404 SbMethod* pMethod = (SbMethod*)pVar;
406 SbModule* pModule = pMethod->GetModule();
407 bool bUseVBAObjects = pModule->IsVBACompat();
408 SbxObject* pObject = pModule->GetParent();
409 @@ -2891,6 +2897,13 @@ void ScInterpreter::ScMacro()
410 pDok->DecMacroInterpretLevel();
411 pDok->UnlockTable( aPos.Tab() );
413 + ScMacroManager* pMacroMgr = pDok->GetMacroManager();
414 + if (pMacroMgr)
416 + bVolatileMacro = pMacroMgr->GetUserFuncVolatile( pMethod->GetName() );
417 + pMacroMgr->AddDependentCell(pModule->GetName(), pMyFormulaCell);
420 SbxDataType eResType = refRes->GetType();
421 if( pVar->GetError() )
422 SetError( errNoValue);
423 @@ -2962,6 +2975,9 @@ void ScInterpreter::ScMacro()
426 pSfxApp->LeaveBasicCall();
428 + if (bVolatileMacro && meVolaileType == NOT_VOLATILE)
429 + meVolaileType = VOLATILE_MACRO;
433 @@ -3619,7 +3635,8 @@ ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc,
434 pTokenMatrixMap( NULL ),
435 pMyFormulaCell( pCell ),
436 pFormatter( pDoc->GetFormatTable() ),
437 - bCalcAsShown( pDoc->GetDocOptions().IsCalcAsShown() )
438 + bCalcAsShown( pDoc->GetDocOptions().IsCalcAsShown() ),
439 + meVolaileType(NOT_VOLATILE)
441 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScTTT" );
442 // pStack = new ScToken*[ MAXSTACK ];
443 @@ -4060,6 +4077,9 @@ StackVar ScInterpreter::Interpret()
444 default : PushError( errUnknownOpCode); break;
447 + if (FormulaCompiler::IsOpCodeVolatile(eOp))
448 + meVolaileType = VOLATILE;
450 // Remember result matrix in case it could be reused.
451 if (pTokenMatrixMap && sp && GetStackType() == svMatrix)
452 pTokenMatrixMap->insert( ScTokenMatrixMap::value_type( pCur,
453 diff --git sc/source/core/tool/interpr5.cxx sc/source/core/tool/interpr5.cxx
454 index c5b4770..854c25d 100644
455 --- sc/source/core/tool/interpr5.cxx
456 +++ sc/source/core/tool/interpr5.cxx
457 @@ -324,6 +324,11 @@ ScMatrixRef ScInterpreter::GetNewMat(SCSIZE nC, SCSIZE nR)
458 return pMat;
461 +ScInterpreter::VolatileType ScInterpreter::GetVolatileType() const
463 + return meVolaileType;
466 ScMatrixRef ScInterpreter::CreateMatrixFromDoubleRef( const FormulaToken* pToken,
467 SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
468 SCCOL nCol2, SCROW nRow2, SCTAB nTab2 )
469 diff --git sc/source/filter/excel/excimp8.cxx sc/source/filter/excel/excimp8.cxx
470 index 60c2f6d..846682b 100644
471 --- sc/source/filter/excel/excimp8.cxx
472 +++ sc/source/filter/excel/excimp8.cxx
473 @@ -99,6 +99,7 @@
474 #include "stlpool.hxx"
475 #include "stlsheet.hxx"
476 #include "detfunc.hxx"
477 +#include "macromgr.hxx"
479 #include <com/sun/star/document/XDocumentProperties.hpp>
480 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
481 @@ -107,6 +108,7 @@
482 #include <cppuhelper/component_context.hxx>
484 #include <com/sun/star/container/XNameContainer.hpp>
485 +#include <sfx2/app.hxx>
487 using namespace com::sun::star;
489 @@ -279,7 +281,24 @@ void ImportExcel8::ReadBasic( void )
490 SvxImportMSVBasic aBasicImport( *pShell, *xRootStrg, bLoadCode, bLoadStrg );
491 bool bAsComment = !bLoadExecutable || !aGlobs.hasValue();
492 aBasicImport.Import( EXC_STORAGE_VBA_PROJECT, EXC_STORAGE_VBA, bAsComment );
493 - GetObjectManager().SetOleNameOverrideInfo( aBasicImport.ControlNameForObjectId() );
494 + if ( !bAsComment )
496 + GetObjectManager().SetOleNameOverrideInfo( aBasicImport.ControlNameForObjectId() );
497 + ScDocument& rDoc = GetDoc();
498 + rDoc.GetMacroManager()->InitUserFuncData();
499 + // Fake ThisComponent being setup by Activate ( which is a view
500 + // related thing ),
501 + // a) if another document is opened then in theory ThisComponent
502 + // will be reset as before,
503 + // b) when this document is 'really' Activated then ThisComponent
504 + // again will be set as before
505 + // The only wrinkle seems if this document is loaded 'InVisible'
506 + // but.. I don't see that this is possible from the vba API
507 + // I could be wrong though
508 + BasicManager* pAppMgr = SFX_APP()->GetBasicManager();
509 + if ( pAppMgr )
510 + pAppMgr->SetGlobalUNOConstant( "ThisComponent", makeAny( pShell->GetModel() ) );
515 diff --git sc/source/ui/docshell/macromgr.cxx sc/source/ui/docshell/macromgr.cxx
516 new file mode 100644
517 index 0000000..97623f3
518 --- /dev/null
519 +++ sc/source/ui/docshell/macromgr.cxx
520 @@ -0,0 +1,217 @@
521 +/*************************************************************************
523 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
525 + * Copyright 2008 by Sun Microsystems, Inc.
527 + * OpenOffice.org - a multi-platform office productivity suite
529 + * $RCSfile: document.hxx,v $
530 + * $Revision: 1.115.36.9 $
532 + * This file is part of OpenOffice.org.
534 + * OpenOffice.org is free software: you can redistribute it and/or modify
535 + * it under the terms of the GNU Lesser General Public License version 3
536 + * only, as published by the Free Software Foundation.
538 + * OpenOffice.org is distributed in the hope that it will be useful,
539 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
540 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
541 + * GNU Lesser General Public License version 3 for more details
542 + * (a copy is included in the LICENSE file that accompanied this code).
544 + * You should have received a copy of the GNU Lesser General Public License
545 + * version 3 along with OpenOffice.org. If not, see
546 + * <http://www.openoffice.org/license.html>
547 + * for a copy of the LGPLv3 License.
549 + ************************************************************************/
551 +// MARKER(update_precomp.py): autogen include statement, do not remove
552 +#include "precompiled_sc.hxx"
554 +// INCLUDE ---------------------------------------------------------------
556 +#include "macromgr.hxx"
557 +#include "document.hxx"
559 +#include "basic/basmgr.hxx"
560 +#include "cppuhelper/implbase1.hxx"
561 +#include "sfx2/objsh.hxx"
562 +#include "cell.hxx"
563 +#include <com/sun/star/container/XContainer.hpp>
565 +#include <list>
567 +using namespace ::com::sun::star;
568 +using ::com::sun::star::uno::RuntimeException;
569 +using ::com::sun::star::uno::Reference;
570 +using ::rtl::OUString;
571 +using ::rtl::OUStringHash;
572 +using ::std::hash_map;
573 +using ::std::list;
574 +using ::std::for_each;
575 +using ::std::pair;
577 +// ============================================================================
579 +/**
580 + * A simple container to keep track of cells that depend on basic modules
581 + * changes. We don't check for duplicates at insertion time; instead, we
582 + * remove duplicates at query time.
583 + */
584 +class ScUserMacroDepTracker
586 +public:
587 + void addCell(const OUString& rModuleName, ScFormulaCell* pCell)
589 + ModuleCellMap::iterator itr = maCells.find(rModuleName);
590 + if (itr == maCells.end())
592 + pair<ModuleCellMap::iterator, bool> r = maCells.insert(
593 + ModuleCellMap::value_type(rModuleName, list<ScFormulaCell*>()));
595 + if (!r.second)
596 + // insertion failed.
597 + return;
599 + itr = r.first;
601 + itr->second.push_back(pCell);
604 + void removeCell(ScFormulaCell* pCell)
606 + ModuleCellMap::iterator itr = maCells.begin(), itrEnd = maCells.end();
607 + for (; itr != itrEnd; ++itr)
608 + itr->second.remove(pCell);
611 + void getCellsByModule(const OUString& rModuleName, list<ScFormulaCell*>& rCells)
613 + ModuleCellMap::iterator itr = maCells.find(rModuleName);
614 + if (itr == maCells.end())
615 + return;
617 + list<ScFormulaCell*>& rCellList = itr->second;
619 + // Remove duplicates.
620 + rCellList.sort();
621 + rCellList.unique();
622 + // exception safe copy
623 + list<ScFormulaCell*> temp(rCellList);
624 + rCells.swap(temp);
627 +private:
628 + typedef hash_map<OUString, list<ScFormulaCell*>, OUStringHash> ModuleCellMap;
629 + ModuleCellMap maCells;
633 +// ============================================================================
635 +ScMacroManager::ScMacroManager(ScDocument* pDoc) :
636 + mpDepTracker(new ScUserMacroDepTracker),
637 + mpDoc(pDoc)
641 +ScMacroManager::~ScMacroManager()
645 +typedef ::cppu::WeakImplHelper1< ::com::sun::star::container::XContainerListener > ContainerListenerHelper;
647 +class VBAProjectListener : public ContainerListenerHelper
649 + ScMacroManager* mpMacroMgr;
650 +public:
651 + VBAProjectListener( ScMacroManager* pMacroMgr ) : mpMacroMgr( pMacroMgr ) {}
652 + // XEventListener
653 + virtual void SAL_CALL disposing( const lang::EventObject& /*Source*/ ) throw(RuntimeException) {}
655 + // XContainerListener
656 + virtual void SAL_CALL elementInserted( const container::ContainerEvent& /*Event*/ ) throw(RuntimeException){}
657 + virtual void SAL_CALL elementReplaced( const container::ContainerEvent& Event ) throw(RuntimeException)
659 + rtl::OUString sModuleName;
660 + Event.Accessor >>= sModuleName;
661 + OSL_TRACE("VBAProjectListener::elementReplaced(%s)", rtl::OUStringToOString( sModuleName, RTL_TEXTENCODING_UTF8 ).getStr() );
662 + mpMacroMgr->InitUserFuncData();
663 + mpMacroMgr->BroadcastModuleUpdate(sModuleName);
665 + virtual void SAL_CALL elementRemoved( const container::ContainerEvent& /*Event*/ ) throw(RuntimeException){}
669 +void ScMacroManager::InitUserFuncData()
671 + // Clear hash_map
672 + mhFuncToVolatile.clear();
673 + String sProjectName( RTL_CONSTASCII_USTRINGPARAM("Standard") );
675 + Reference< container::XContainer > xModuleContainer;
676 + SfxObjectShell* pShell = mpDoc->GetDocumentShell();
677 + if ( pShell && pShell->GetBasicManager()->GetName().Len() > 0 )
678 + sProjectName = pShell->GetBasicManager()->GetName();
679 + try
680 + {
681 + Reference< script::XLibraryContainer > xLibraries( pShell->GetBasicContainer(), uno::UNO_QUERY_THROW );
682 + xModuleContainer.set( xLibraries->getByName( sProjectName ), uno::UNO_QUERY_THROW );
684 + if ( xModuleContainer.is() )
686 + // remove old listener ( if there was one )
687 + if ( mxContainerListener.is() )
688 + xModuleContainer->removeContainerListener( mxContainerListener );
689 + // Create listener
690 + mxContainerListener = new VBAProjectListener( this );
691 + xModuleContainer->addContainerListener( mxContainerListener );
694 + catch( uno::Exception& )
699 +void ScMacroManager::SetUserFuncVolatile( const OUString& sName, bool isVolatile )
701 + mhFuncToVolatile[ sName ] = isVolatile;
704 +bool ScMacroManager::GetUserFuncVolatile( const OUString& sName )
706 + NameBoolMap::iterator it = mhFuncToVolatile.find( sName );
707 + if ( it == mhFuncToVolatile.end() )
708 + return false;
709 + return it->second;
712 +void ScMacroManager::AddDependentCell(const OUString& aModuleName, ScFormulaCell* pCell)
714 + mpDepTracker->addCell(aModuleName, pCell);
717 +void ScMacroManager::RemoveDependentCell(ScFormulaCell* pCell)
719 + mpDepTracker->removeCell(pCell);
722 +void ScMacroManager::BroadcastModuleUpdate(const OUString& aModuleName)
724 + list<ScFormulaCell*> aCells;
725 + mpDepTracker->getCellsByModule(aModuleName, aCells);
726 + list<ScFormulaCell*>::iterator itr = aCells.begin(), itrEnd = aCells.end();
727 + for (; itr != itrEnd; ++itr)
728 + {
729 + ScFormulaCell* pCell = *itr;
730 + mpDoc->PutInFormulaTree(pCell); // for F9 recalc
732 + // for recalc on cell value change. If the cell is not volatile, the
733 + // cell stops listening right away after it gets re-interpreted.
734 + mpDoc->StartListeningArea(BCA_LISTEN_ALWAYS, pCell);
738 diff --git sc/source/ui/docshell/makefile.mk sc/source/ui/docshell/makefile.mk
739 index b48627e..e96d750 100644
740 --- sc/source/ui/docshell/makefile.mk
741 +++ sc/source/ui/docshell/makefile.mk
742 @@ -95,7 +95,8 @@ SLOFILES = \
743 $(SLO)$/hiranges.obj \
744 $(SLO)$/pntlock.obj \
745 $(SLO)$/sizedev.obj \
746 - $(SLO)$/editable.obj
747 + $(SLO)$/editable.obj \
748 + $(SLO)$/macromgr.obj
751 EXCEPTIONSFILES= \
752 @@ -105,7 +106,8 @@ EXCEPTIONSFILES= \
753 $(SLO)$/docsh8.obj \
754 $(SLO)$/externalrefmgr.obj \
755 $(SLO)$/dbdocimp.obj \
756 - $(SLO)$/docfunc.obj
757 + $(SLO)$/docfunc.obj \
758 + $(SLO)$/macromgr.obj
760 SRS1NAME=$(TARGET)
761 SRC1FILES = tpstat.src
762 @@ -135,7 +137,8 @@ LIB1OBJFILES = \
763 $(SLO)$/hiranges.obj \
764 $(SLO)$/pntlock.obj \
765 $(SLO)$/sizedev.obj \
766 - $(SLO)$/editable.obj
767 + $(SLO)$/editable.obj \
768 + $(SLO)$/macromgr.obj
770 # --- Tagets -------------------------------------------------------
772 diff --git sc/source/ui/vba/vbaapplication.cxx sc/source/ui/vba/vbaapplication.cxx
773 index 69121a0..c26a61d 100644
774 --- sc/source/ui/vba/vbaapplication.cxx
775 +++ sc/source/ui/vba/vbaapplication.cxx
776 @@ -61,6 +61,7 @@
777 #include "vbatextboxshape.hxx"
778 #include "vbaassistant.hxx"
779 #include "sc.hrc"
780 +#include "macromgr.hxx"
782 #include <osl/file.hxx>
784 @@ -87,7 +88,12 @@
785 #include "unonames.hxx"
786 #include "docsh.hxx"
787 #include <vbahelper/helperdecl.hxx>
789 +#include <basic/sbmeth.hxx>
790 +#include <basic/sbmod.hxx>
791 +#include <basic/sbstar.hxx>
792 +#include <basic/sbx.hxx>
793 +#include <basic/sbxobj.hxx>
794 +#include <basic/sbuno.hxx>
795 using namespace ::ooo::vba;
796 using namespace ::com::sun::star;
797 using ::com::sun::star::uno::Reference;
798 @@ -1111,6 +1117,16 @@ ScVbaApplication::Volatile( const uno::Any& aVolatile ) throw ( uno::RuntimeExc
800 sal_Bool bVolatile = sal_True;
801 aVolatile >>= bVolatile;
802 + SbMethod* pMeth = StarBASIC::GetActiveMethod();
803 + if ( pMeth )
805 + OSL_TRACE("ScVbaApplication::Volatile() In method ->%s<-", rtl::OUStringToOString( pMeth->GetName(), RTL_TEXTENCODING_UTF8 ).getStr() );
806 + uno::Reference< frame::XModel > xModel( getCurrentDocument() );
807 + ScDocument* pDoc = excel::getDocShell( xModel )->GetDocument();
808 + pDoc->GetMacroManager()->SetUserFuncVolatile( pMeth->GetName(), bVolatile);
811 +// this is bound to break when loading the document
812 return;
814 if ( bVolatile )
815 diff --git sc/source/ui/vba/vbadialog.cxx sc/source/ui/vba/vbadialog.cxx
816 index 7383f5d..abfa6d3 100644
817 --- sc/source/ui/vba/vbadialog.cxx
818 +++ sc/source/ui/vba/vbadialog.cxx
819 @@ -47,6 +47,7 @@ void
820 ScVbaDialog::Show() throw(uno::RuntimeException)
822 rtl::OUString aURL;
823 + // #FIXME - should this really use the current document?
824 uno::Reference< frame::XModel > xModel = getCurrentDocument();
825 if ( xModel.is() )
827 diff --git sc/source/ui/vba/vbarange.cxx sc/source/ui/vba/vbarange.cxx
828 index 7a31267..5f62736 100644
829 --- sc/source/ui/vba/vbarange.cxx
830 +++ sc/source/ui/vba/vbarange.cxx
831 @@ -1976,6 +1976,7 @@ ScVbaRange::Select() throw (uno::RuntimeException)
832 // ThisComponent.CurrentController.Frame.getContainerWindow.SetFocus
835 + // #FIXME don't use current document
836 uno::Reference< frame::XController > xController( getCurrentDocument()->getCurrentController(), uno::UNO_QUERY_THROW );
837 uno::Reference< frame::XFrame > xFrame( xController->getFrame(), uno::UNO_QUERY_THROW );
838 uno::Reference< awt::XWindow > xWin( xFrame->getContainerWindow(), uno::UNO_QUERY_THROW );
839 @@ -2026,8 +2027,10 @@ ScVbaRange::Activate() throw (uno::RuntimeException)
840 table::CellRangeAddress thisRangeAddress = xThisRangeAddress->getRangeAddress();
842 // get current selection
843 + // #FIXME don't use getCurrentDocument
844 uno::Reference< sheet::XCellRangeAddressable > xRange( getCurrentDocument()->getCurrentSelection(), ::uno::UNO_QUERY);
846 + // #FIXME don't use getCurrentDocument
847 uno::Reference< sheet::XSheetCellRanges > xRanges( getCurrentDocument()->getCurrentSelection(), ::uno::UNO_QUERY);
849 if ( xRanges.is() )
850 @@ -2541,8 +2544,10 @@ ScVbaRange::PasteSpecial( const uno::Any& Paste, const uno::Any& Operation, cons
852 if ( m_Areas->getCount() > 1 )
853 throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("That command cannot be used on multiple selections" ) ), uno::Reference< uno::XInterface >() );
854 + // #FIXME doen't use current document
855 uno::Reference< view::XSelectionSupplier > xSelection( getCurrentDocument()->getCurrentController(), uno::UNO_QUERY_THROW );
856 // save old selection
857 + // #FIXME doen't use current document
858 uno::Reference< uno::XInterface > xSel( getCurrentDocument()->getCurrentSelection() );
859 // select this range
860 xSelection->select( uno::makeAny( mxRange ) );
861 @@ -3900,6 +3905,7 @@ ScVbaRange::ApplicationRange( const uno::Reference< uno::XComponentContext >& xC
865 + // #FIXME don't use current document
866 uno::Reference< sheet::XSpreadsheetView > xView( getCurrentDocument()->getCurrentController(), uno::UNO_QUERY );
867 uno::Reference< table::XCellRange > xSheetRange( xView->getActiveSheet(), uno::UNO_QUERY_THROW );
868 ScVbaRange* pRange = new ScVbaRange( uno::Reference< XHelperInterface >(), xContext, xSheetRange );
869 diff --git sc/source/ui/vba/vbashape.cxx sc/source/ui/vba/vbashape.cxx
870 index a8d9e82..a231cad 100644
871 --- sc/source/ui/vba/vbashape.cxx
872 +++ sc/source/ui/vba/vbashape.cxx
873 @@ -431,6 +431,7 @@ ScVbaShape::ScaleWidth( double Factor, sal_Bool /*RelativeToOriginalSize*/, sal_
874 void SAL_CALL
875 ScVbaShape::Select( const uno::Any& /*Replace*/ ) throw ( uno::RuntimeException )
877 + // #FIXME don't use getCurrentDocument
878 uno::Reference< frame::XModel > xModel( getCurrentDocument(), uno::UNO_QUERY_THROW );
879 uno::Reference< view::XSelectionSupplier > xSelectSupp( xModel->getCurrentController(), uno::UNO_QUERY_THROW );
880 xSelectSupp->select( uno::makeAny( m_xShape ) );
881 diff --git sc/source/ui/vba/vbashaperange.cxx sc/source/ui/vba/vbashaperange.cxx
882 index 8aebaea..5890e43 100644
883 --- sc/source/ui/vba/vbashaperange.cxx
884 +++ sc/source/ui/vba/vbashaperange.cxx
885 @@ -66,6 +66,7 @@ ScVbaShapeRange::ScVbaShapeRange( const uno::Reference< XHelperInterface >& xPar
886 void SAL_CALL
887 ScVbaShapeRange::Select( ) throw (uno::RuntimeException)
889 + // #FIXME don't use getCurrentDocument
890 uno::Reference< frame::XModel > xModel( getCurrentDocument(), uno::UNO_QUERY_THROW );
891 uno::Reference< view::XSelectionSupplier > xSelectSupp( xModel->getCurrentController(), uno::UNO_QUERY_THROW );
892 xSelectSupp->select( uno::makeAny( getShapes() ) );
893 diff --git sc/source/ui/vba/vbashapes.cxx sc/source/ui/vba/vbashapes.cxx
894 index 80c1e8f..c1013ba 100644
895 --- sc/source/ui/vba/vbashapes.cxx
896 +++ sc/source/ui/vba/vbashapes.cxx
897 @@ -219,6 +219,7 @@ ScVbaShapes::SelectAll() throw (uno::RuntimeException)
898 uno::Reference< drawing::XShape >
899 ScVbaShapes::createShape( rtl::OUString service ) throw (css::uno::RuntimeException)
901 + // #FIXME don't use getCurrentDocument
902 uno::Reference< lang::XMultiServiceFactory > xMSF( getCurrentDocument(), uno::UNO_QUERY_THROW );
903 uno::Reference< drawing::XShape > xShape( xMSF->createInstance( service ), uno::UNO_QUERY_THROW );
904 return xShape;