Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <vcl/svapp.hxx>
31 : : #include <sfx2/viewfrm.hxx>
32 : : #include <sfx2/dispatch.hxx>
33 : : #include <svx/dataaccessdescriptor.hxx>
34 : : #include <comphelper/servicehelper.hxx>
35 : : #include <unodispatch.hxx>
36 : : #include <unobaseclass.hxx>
37 : : #include <view.hxx>
38 : : #include <cmdid.h>
39 : : #include "wrtsh.hxx"
40 : : #include "dbmgr.hxx"
41 : :
42 : :
43 : : using namespace ::com::sun::star;
44 : :
45 : : using ::rtl::OUString;
46 : :
47 : : const char* cURLStart = ".uno:DataSourceBrowser/";
48 : : const char* cURLFormLetter = ".uno:DataSourceBrowser/FormLetter";
49 : : const char* cURLInsertContent = ".uno:DataSourceBrowser/InsertContent";//data into fields
50 : : const char* cURLInsertColumns = ".uno:DataSourceBrowser/InsertColumns";//data into text
51 : : const char* cURLDocumentDataSource = ".uno:DataSourceBrowser/DocumentDataSource";//current data source of the document
52 : : const sal_Char* cInternalDBChangeNotification = ".uno::Writer/DataSourceChanged";
53 : :
54 : 1318 : SwXDispatchProviderInterceptor::SwXDispatchProviderInterceptor(SwView& rVw) :
55 : 1318 : m_pView(&rVw)
56 : : {
57 [ + - ][ + - ]: 1318 : uno::Reference< frame::XFrame> xUnoFrame = m_pView->GetViewFrame()->GetFrame().GetFrameInterface();
58 [ + - ][ + - ]: 1318 : m_xIntercepted = uno::Reference< frame::XDispatchProviderInterception>(xUnoFrame, uno::UNO_QUERY);
59 [ + - ]: 1318 : if(m_xIntercepted.is())
60 : : {
61 : 1318 : m_refCount++;
62 [ + - ][ + - ]: 1318 : m_xIntercepted->registerDispatchProviderInterceptor((frame::XDispatchProviderInterceptor*)this);
[ + - ]
63 : : // this should make us the top-level dispatch-provider for the component, via a call to our
64 : : // setDispatchProvider we should have got an fallback for requests we (i.e. our master) cannot fullfill
65 [ + - ]: 1318 : uno::Reference< lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY);
66 [ + - ]: 1318 : if (xInterceptedComponent.is())
67 [ + - ][ + - ]: 1318 : xInterceptedComponent->addEventListener((lang::XEventListener*)this);
[ + - ]
68 : 1318 : m_refCount--;
69 : 1318 : }
70 : 1318 : }
71 : :
72 : 1231 : SwXDispatchProviderInterceptor::~SwXDispatchProviderInterceptor()
73 : : {
74 [ - + ]: 2462 : }
75 : :
76 : 144624 : uno::Reference< frame::XDispatch > SwXDispatchProviderInterceptor::queryDispatch(
77 : : const util::URL& aURL, const OUString& aTargetFrameName, sal_Int32 nSearchFlags )
78 : : throw(uno::RuntimeException)
79 : : {
80 [ + - ]: 144624 : DispatchMutexLock_Impl aLock(*this);
81 : 144624 : uno::Reference< frame::XDispatch> xResult;
82 : : // create some dispatch ...
83 [ + + ][ + + ]: 144624 : if(m_pView && !aURL.Complete.compareToAscii(cURLStart, 23))
[ + - ]
84 : : {
85 [ + + + + : 20 : if(!aURL.Complete.compareToAscii(cURLFormLetter) ||
+ + + - ]
[ + - ]
86 : 6 : !aURL.Complete.compareToAscii(cURLInsertContent) ||
87 : 4 : !aURL.Complete.compareToAscii(cURLInsertColumns)||
88 : 2 : !aURL.Complete.compareToAscii(cURLDocumentDataSource))
89 : : {
90 [ + + ]: 8 : if(!m_xDispatch.is())
91 [ + - ][ + - ]: 2 : m_xDispatch = new SwXDispatch(*m_pView);
[ + - ]
92 [ + - ]: 8 : xResult = m_xDispatch;
93 : : }
94 : : }
95 : :
96 : : // ask our slave provider
97 [ + + ][ + - ]: 144624 : if (!xResult.is() && m_xSlaveDispatcher.is())
[ + + ]
98 [ + - ][ + - ]: 144616 : xResult = m_xSlaveDispatcher->queryDispatch(aURL, aTargetFrameName, nSearchFlags);
[ + - ]
99 : :
100 [ + - ]: 144624 : return xResult;
101 : : }
102 : :
103 : 0 : uno::Sequence< uno::Reference< frame::XDispatch > > SwXDispatchProviderInterceptor::queryDispatches(
104 : : const uno::Sequence< frame::DispatchDescriptor >& aDescripts ) throw(uno::RuntimeException)
105 : : {
106 [ # # ]: 0 : DispatchMutexLock_Impl aLock(*this);
107 [ # # ]: 0 : uno::Sequence< uno::Reference< frame::XDispatch> > aReturn(aDescripts.getLength());
108 [ # # ]: 0 : uno::Reference< frame::XDispatch>* pReturn = aReturn.getArray();
109 : 0 : const frame::DispatchDescriptor* pDescripts = aDescripts.getConstArray();
110 [ # # ]: 0 : for (sal_Int16 i=0; i<aDescripts.getLength(); ++i, ++pReturn, ++pDescripts)
111 : : {
112 : : *pReturn = queryDispatch(pDescripts->FeatureURL,
113 [ # # ][ # # ]: 0 : pDescripts->FrameName, pDescripts->SearchFlags);
114 : : }
115 [ # # ]: 0 : return aReturn;
116 : : }
117 : :
118 : 1231 : uno::Reference< frame::XDispatchProvider > SwXDispatchProviderInterceptor::getSlaveDispatchProvider( )
119 : : throw(uno::RuntimeException)
120 : : {
121 [ + - ]: 1231 : DispatchMutexLock_Impl aLock(*this);
122 [ + - ]: 1231 : return m_xSlaveDispatcher;
123 : : }
124 : :
125 : 2549 : void SwXDispatchProviderInterceptor::setSlaveDispatchProvider(
126 : : const uno::Reference< frame::XDispatchProvider >& xNewDispatchProvider ) throw(uno::RuntimeException)
127 : : {
128 [ + - ]: 2549 : DispatchMutexLock_Impl aLock(*this);
129 [ + - ][ + - ]: 2549 : m_xSlaveDispatcher = xNewDispatchProvider;
130 : 2549 : }
131 : :
132 : 1231 : uno::Reference< frame::XDispatchProvider > SwXDispatchProviderInterceptor::getMasterDispatchProvider( )
133 : : throw(uno::RuntimeException)
134 : : {
135 [ + - ]: 1231 : DispatchMutexLock_Impl aLock(*this);
136 [ + - ]: 1231 : return m_xMasterDispatcher;
137 : : }
138 : :
139 : 2549 : void SwXDispatchProviderInterceptor::setMasterDispatchProvider(
140 : : const uno::Reference< frame::XDispatchProvider >& xNewSupplier ) throw(uno::RuntimeException)
141 : : {
142 [ + - ]: 2549 : DispatchMutexLock_Impl aLock(*this);
143 [ + - ][ + - ]: 2549 : m_xMasterDispatcher = xNewSupplier;
144 : 2549 : }
145 : :
146 : 0 : void SwXDispatchProviderInterceptor::disposing( const lang::EventObject& )
147 : : throw(uno::RuntimeException)
148 : : {
149 [ # # ]: 0 : DispatchMutexLock_Impl aLock(*this);
150 [ # # ]: 0 : if (m_xIntercepted.is())
151 : : {
152 [ # # ][ # # ]: 0 : m_xIntercepted->releaseDispatchProviderInterceptor((frame::XDispatchProviderInterceptor*)this);
[ # # ]
153 [ # # ]: 0 : uno::Reference< lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY);
154 [ # # ]: 0 : if (xInterceptedComponent.is())
155 [ # # ][ # # ]: 0 : xInterceptedComponent->removeEventListener((lang::XEventListener*)this);
[ # # ]
156 [ # # ]: 0 : m_xDispatch = 0;
157 : : }
158 [ # # ][ # # ]: 0 : m_xIntercepted = NULL;
159 : 0 : }
160 : :
161 : : namespace
162 : : {
163 : : class theSwXDispatchProviderInterceptorUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSwXDispatchProviderInterceptorUnoTunnelId > {};
164 : : }
165 : :
166 : 2462 : const uno::Sequence< sal_Int8 > & SwXDispatchProviderInterceptor::getUnoTunnelId()
167 : : {
168 : 2462 : return theSwXDispatchProviderInterceptorUnoTunnelId::get().getSeq();
169 : : }
170 : :
171 : 1231 : sal_Int64 SwXDispatchProviderInterceptor::getSomething(
172 : : const uno::Sequence< sal_Int8 >& aIdentifier )
173 : : throw(uno::RuntimeException)
174 : : {
175 [ + - + - ]: 2462 : if( aIdentifier.getLength() == 16
[ + - ]
176 : 1231 : && 0 == memcmp( getUnoTunnelId().getConstArray(),
177 : 1231 : aIdentifier.getConstArray(), 16 ) )
178 : : {
179 : 1231 : return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this ));
180 : : }
181 : 1231 : return 0;
182 : : }
183 : :
184 : 1231 : void SwXDispatchProviderInterceptor::Invalidate()
185 : : {
186 [ + - ]: 1231 : DispatchMutexLock_Impl aLock(*this);
187 [ + - ]: 1231 : if (m_xIntercepted.is())
188 : : {
189 [ + - ][ + - ]: 1231 : m_xIntercepted->releaseDispatchProviderInterceptor((frame::XDispatchProviderInterceptor*)this);
[ + - ]
190 [ + - ]: 1231 : uno::Reference< lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY);
191 [ + - ]: 1231 : if (xInterceptedComponent.is())
192 [ + - ][ + - ]: 1231 : xInterceptedComponent->removeEventListener((lang::XEventListener*)this);
[ + - ]
193 [ + - ]: 1231 : m_xDispatch = 0;
194 : : }
195 [ + - ]: 1231 : m_xIntercepted = NULL;
196 [ + - ]: 1231 : m_pView = 0;
197 : 1231 : }
198 : :
199 : 2 : SwXDispatch::SwXDispatch(SwView& rVw) :
200 : : m_pView(&rVw),
201 : : m_bOldEnable(sal_False),
202 [ + - ]: 2 : m_bListenerAdded(sal_False)
203 : : {
204 : 2 : }
205 : :
206 : 2 : SwXDispatch::~SwXDispatch()
207 : : {
208 [ - + ][ # # ]: 2 : if(m_bListenerAdded && m_pView)
209 : : {
210 [ # # ][ # # ]: 0 : uno::Reference<view::XSelectionSupplier> xSupplier = m_pView->GetUNOObject();
211 [ # # ]: 0 : uno::Reference<view::XSelectionChangeListener> xThis = this;
212 [ # # ][ # # ]: 0 : xSupplier->removeSelectionChangeListener(xThis);
213 : : }
214 [ - + ]: 4 : }
215 : :
216 : 0 : void SwXDispatch::dispatch(
217 : : const util::URL& aURL, const uno::Sequence< beans::PropertyValue >& aArgs ) throw(uno::RuntimeException)
218 : : {
219 [ # # ]: 0 : if(!m_pView)
220 [ # # ]: 0 : throw uno::RuntimeException();
221 : 0 : SwWrtShell& rSh = m_pView->GetWrtShell();
222 : 0 : SwNewDBMgr* pNewDBMgr = rSh.GetNewDBMgr();
223 [ # # ]: 0 : if(!aURL.Complete.compareToAscii(cURLInsertContent))
224 : : {
225 [ # # ]: 0 : ::svx::ODataAccessDescriptor aDescriptor(aArgs);
226 [ # # ]: 0 : SwMergeDescriptor aMergeDesc( DBMGR_MERGE, rSh, aDescriptor );
227 [ # # ][ # # ]: 0 : pNewDBMgr->MergeNew(aMergeDesc);
[ # # ]
228 : : }
229 [ # # ]: 0 : else if(!aURL.Complete.compareToAscii(cURLInsertColumns))
230 : : {
231 : 0 : pNewDBMgr->InsertText(rSh, aArgs);
232 : : }
233 [ # # ]: 0 : else if(!aURL.Complete.compareToAscii(cURLFormLetter))
234 : : {
235 [ # # ][ # # ]: 0 : SfxUsrAnyItem aDBProperties(FN_PARAM_DATABASE_PROPERTIES, uno::makeAny(aArgs));
236 : : m_pView->GetViewFrame()->GetDispatcher()->Execute(
237 : : FN_MAILMERGE_WIZARD,
238 : : SFX_CALLMODE_ASYNCHRON,
239 [ # # ][ # # ]: 0 : &aDBProperties, 0L);
240 : : }
241 [ # # ]: 0 : else if(!aURL.Complete.compareToAscii(cURLDocumentDataSource))
242 : : {
243 : : OSL_FAIL("SwXDispatch::dispatch: this URL is not to be dispatched!");
244 : : }
245 [ # # ]: 0 : else if(!aURL.Complete.compareToAscii(cInternalDBChangeNotification))
246 : : {
247 [ # # ]: 0 : frame::FeatureStateEvent aEvent;
248 : 0 : aEvent.IsEnabled = sal_True;
249 [ # # ][ # # ]: 0 : aEvent.Source = *(cppu::OWeakObject*)this;
250 : :
251 [ # # ]: 0 : const SwDBData& rData = m_pView->GetWrtShell().GetDBDesc();
252 [ # # ]: 0 : ::svx::ODataAccessDescriptor aDescriptor;
253 [ # # ]: 0 : aDescriptor.setDataSource(rData.sDataSource);
254 [ # # ][ # # ]: 0 : aDescriptor[::svx::daCommand] <<= rData.sCommand;
255 [ # # ][ # # ]: 0 : aDescriptor[::svx::daCommandType] <<= rData.nCommandType;
256 : :
257 [ # # ][ # # ]: 0 : aEvent.State <<= aDescriptor.createPropertyValueSequence();
[ # # ]
258 : 0 : aEvent.IsEnabled = !rData.sDataSource.isEmpty();
259 : :
260 : 0 : StatusListenerList::iterator aListIter = m_aListenerList.begin();
261 [ # # ]: 0 : for(aListIter = m_aListenerList.begin(); aListIter != m_aListenerList.end(); ++aListIter)
262 : : {
263 [ # # ]: 0 : StatusStruct_Impl aStatus = *aListIter;
264 [ # # ]: 0 : if(!aStatus.aURL.Complete.compareToAscii(cURLDocumentDataSource))
265 : : {
266 : 0 : aEvent.FeatureURL = aStatus.aURL;
267 [ # # ][ # # ]: 0 : aStatus.xListener->statusChanged( aEvent );
268 : : }
269 [ # # ][ # # ]: 0 : }
[ # # ]
270 : : }
271 : : else
272 [ # # ]: 0 : throw uno::RuntimeException();
273 : :
274 : 0 : }
275 : :
276 : 8 : void SwXDispatch::addStatusListener(
277 : : const uno::Reference< frame::XStatusListener >& xControl, const util::URL& aURL ) throw(uno::RuntimeException)
278 : : {
279 [ - + ]: 8 : if(!m_pView)
280 [ # # ]: 0 : throw uno::RuntimeException();
281 [ + - ]: 8 : ShellModes eMode = m_pView->GetShellMode();
282 : : sal_Bool bEnable = SHELL_MODE_TEXT == eMode ||
283 : : SHELL_MODE_LIST_TEXT == eMode ||
284 : : SHELL_MODE_TABLE_TEXT == eMode ||
285 [ - + ][ # # ]: 8 : SHELL_MODE_TABLE_LIST_TEXT == eMode;
[ # # ][ # # ]
286 : :
287 : 8 : m_bOldEnable = bEnable;
288 [ + - ]: 8 : frame::FeatureStateEvent aEvent;
289 : 8 : aEvent.IsEnabled = bEnable;
290 [ + - ][ + - ]: 8 : aEvent.Source = *(cppu::OWeakObject*)this;
291 : 8 : aEvent.FeatureURL = aURL;
292 : :
293 : : // one of the URLs requires a special state ....
294 [ + + ]: 8 : if (!aURL.Complete.compareToAscii(cURLDocumentDataSource))
295 : : {
296 [ + - ]: 2 : const SwDBData& rData = m_pView->GetWrtShell().GetDBDesc();
297 : :
298 [ + - ]: 2 : ::svx::ODataAccessDescriptor aDescriptor;
299 [ + - ]: 2 : aDescriptor.setDataSource(rData.sDataSource);
300 [ + - ][ + - ]: 2 : aDescriptor[::svx::daCommand] <<= rData.sCommand;
301 [ + - ][ + - ]: 2 : aDescriptor[::svx::daCommandType] <<= rData.nCommandType;
302 : :
303 [ + - ][ + - ]: 2 : aEvent.State <<= aDescriptor.createPropertyValueSequence();
[ + - ]
304 [ + - ]: 2 : aEvent.IsEnabled = !rData.sDataSource.isEmpty();
305 : : }
306 : :
307 : :
308 [ + - ][ + - ]: 8 : xControl->statusChanged( aEvent );
309 : :
310 : 8 : StatusListenerList::iterator aListIter = m_aListenerList.begin();
311 [ + - ]: 8 : StatusStruct_Impl aStatus;
312 [ + - ]: 8 : aStatus.xListener = xControl;
313 : 8 : aStatus.aURL = aURL;
314 [ + - ]: 8 : m_aListenerList.insert(aListIter, aStatus);
315 : :
316 [ + + ]: 8 : if(!m_bListenerAdded)
317 : : {
318 [ + - ][ + - ]: 2 : uno::Reference<view::XSelectionSupplier> xSupplier = m_pView->GetUNOObject();
319 [ + - ]: 2 : uno::Reference<view::XSelectionChangeListener> xThis = this;
320 [ + - ][ + - ]: 2 : xSupplier->addSelectionChangeListener(xThis);
321 : 2 : m_bListenerAdded = sal_True;
322 [ + - ][ + - ]: 8 : }
323 : 8 : }
324 : :
325 : 8 : void SwXDispatch::removeStatusListener(
326 : : const uno::Reference< frame::XStatusListener >& xControl, const util::URL& ) throw(uno::RuntimeException)
327 : : {
328 : 8 : StatusListenerList::iterator aListIter = m_aListenerList.begin();
329 [ + - ]: 16 : for(aListIter = m_aListenerList.begin(); aListIter != m_aListenerList.end(); ++aListIter)
330 : : {
331 [ + - ]: 8 : StatusStruct_Impl aStatus = *aListIter;
332 [ + - ][ + - ]: 8 : if(aStatus.xListener.get() == xControl.get())
[ + - ]
333 : : {
334 [ + - ]: 8 : m_aListenerList.erase(aListIter);
335 : : break;
336 : : }
337 [ + - ][ - + ]: 8 : }
338 [ + + ][ + - ]: 8 : if(m_aListenerList.empty() && m_pView)
[ + + ]
339 : : {
340 [ + - ][ + - ]: 2 : uno::Reference<view::XSelectionSupplier> xSupplier = m_pView->GetUNOObject();
341 [ + - ]: 2 : uno::Reference<view::XSelectionChangeListener> xThis = this;
342 [ + - ][ + - ]: 2 : xSupplier->removeSelectionChangeListener(xThis);
343 : 2 : m_bListenerAdded = sal_False;
344 : : }
345 : 8 : }
346 : :
347 : 0 : void SwXDispatch::selectionChanged( const lang::EventObject& ) throw(uno::RuntimeException)
348 : : {
349 : 0 : ShellModes eMode = m_pView->GetShellMode();
350 : : sal_Bool bEnable = SHELL_MODE_TEXT == eMode ||
351 : : SHELL_MODE_LIST_TEXT == eMode ||
352 : : SHELL_MODE_TABLE_TEXT == eMode ||
353 [ # # ][ # # ]: 0 : SHELL_MODE_TABLE_LIST_TEXT == eMode;
[ # # ][ # # ]
354 [ # # ]: 0 : if(bEnable != m_bOldEnable)
355 : : {
356 : 0 : m_bOldEnable = bEnable;
357 [ # # ]: 0 : frame::FeatureStateEvent aEvent;
358 : 0 : aEvent.IsEnabled = bEnable;
359 [ # # ][ # # ]: 0 : aEvent.Source = *(cppu::OWeakObject*)this;
360 : :
361 : 0 : StatusListenerList::iterator aListIter = m_aListenerList.begin();
362 [ # # ]: 0 : for(aListIter = m_aListenerList.begin(); aListIter != m_aListenerList.end(); ++aListIter)
363 : : {
364 [ # # ]: 0 : StatusStruct_Impl aStatus = *aListIter;
365 : 0 : aEvent.FeatureURL = aStatus.aURL;
366 [ # # ]: 0 : if (0 != aStatus.aURL.Complete.compareToAscii(cURLDocumentDataSource))
367 : : // the document's data source does not depend on the selection, so it's state does not change here
368 [ # # ][ # # ]: 0 : aStatus.xListener->statusChanged( aEvent );
369 [ # # ][ # # ]: 0 : }
370 : : }
371 : 0 : }
372 : :
373 : 0 : void SwXDispatch::disposing( const lang::EventObject& rSource ) throw(uno::RuntimeException)
374 : : {
375 [ # # ]: 0 : uno::Reference<view::XSelectionSupplier> xSupplier(rSource.Source, uno::UNO_QUERY);
376 [ # # ]: 0 : uno::Reference<view::XSelectionChangeListener> xThis = this;
377 [ # # ][ # # ]: 0 : xSupplier->removeSelectionChangeListener(xThis);
378 : 0 : m_bListenerAdded = sal_False;
379 : :
380 [ # # ]: 0 : lang::EventObject aObject;
381 [ # # ]: 0 : aObject.Source = (cppu::OWeakObject*)this;
382 : 0 : StatusListenerList::iterator aListIter = m_aListenerList.begin();
383 [ # # ]: 0 : for(; aListIter != m_aListenerList.end(); ++aListIter)
384 : : {
385 [ # # ]: 0 : StatusStruct_Impl aStatus = *aListIter;
386 [ # # ][ # # ]: 0 : aStatus.xListener->disposing(aObject);
387 [ # # ]: 0 : }
388 [ # # ]: 0 : m_pView = 0;
389 : 0 : }
390 : :
391 : 0 : const sal_Char* SwXDispatch::GetDBChangeURL()
392 : : {
393 : 0 : return cInternalDBChangeNotification;
394 : : }
395 : :
396 : 153415 : SwXDispatchProviderInterceptor::DispatchMutexLock_Impl::DispatchMutexLock_Impl(
397 : : SwXDispatchProviderInterceptor& ) :
398 : 153415 : aGuard(Application::GetSolarMutex())
399 : : {
400 : 153415 : }
401 : :
402 : 153415 : SwXDispatchProviderInterceptor::DispatchMutexLock_Impl::~DispatchMutexLock_Impl()
403 : : {
404 : 153415 : }
405 : :
406 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|