Avoid potential negative array index access to cached text.
[LibreOffice.git] / scripting / source / dlgprov / dlgprov.cxx
blob32e85900d440d7daca71873762ccc2cce01bdc88
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 .
21 #include "dlgprov.hxx"
22 #include "dlgevtatt.hxx"
23 #include <com/sun/star/awt/UnoControlDialog.hpp>
24 #include <com/sun/star/awt/Toolkit.hpp>
25 #include <com/sun/star/awt/XControlContainer.hpp>
26 #include <com/sun/star/awt/XWindowPeer.hpp>
27 #include <com/sun/star/beans/theIntrospection.hpp>
28 #include <com/sun/star/beans/XPropertySet.hpp>
29 #include <com/sun/star/document/XEmbeddedScripts.hpp>
30 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
31 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
32 #include <com/sun/star/io/XInputStreamProvider.hpp>
33 #include <com/sun/star/resource/XStringResourceSupplier.hpp>
34 #include <com/sun/star/resource/XStringResourceManager.hpp>
35 #include <com/sun/star/script/XLibraryContainer.hpp>
36 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
37 #include <com/sun/star/uri/XUriReference.hpp>
38 #include <com/sun/star/uri/UriReferenceFactory.hpp>
39 #include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
40 #include <com/sun/star/uri/XVndSunStarExpandUrl.hpp>
41 #include <com/sun/star/util/theMacroExpander.hpp>
43 #include <cppuhelper/exc_hlp.hxx>
44 #include <cppuhelper/supportsservice.hxx>
45 #include <sfx2/app.hxx>
46 #include <xmlscript/xmldlg_imexp.hxx>
47 #include <tools/urlobj.hxx>
48 #include <comphelper/namedvaluecollection.hxx>
49 #include <util/MiscUtils.hxx>
50 #include <vcl/settings.hxx>
51 #include <vcl/svapp.hxx>
52 #include <i18nlangtag/languagetag.hxx>
54 using namespace ::com::sun::star;
55 using namespace awt;
56 using namespace lang;
57 using namespace uno;
58 using namespace script;
59 using namespace beans;
60 using namespace document;
61 using namespace ::sf_misc;
63 namespace dlgprov
66 Reference< resource::XStringResourceManager > lcl_getStringResourceManager(const Reference< XComponentContext >& i_xContext, std::u16string_view i_sURL)
68 INetURLObject aInetObj( i_sURL );
69 OUString aDlgName = aInetObj.GetBase();
70 aInetObj.removeSegment();
71 OUString aDlgLocation = aInetObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
72 css::lang::Locale aLocale = Application::GetSettings().GetUILanguageTag().getLocale();
74 Reference< task::XInteractionHandler > xDummyHandler;
76 Sequence<Any> aArgs{ Any(aDlgLocation),
77 Any(true), // bReadOnly
78 Any(aLocale),
79 Any(aDlgName),
80 Any(OUString()),
81 Any(xDummyHandler) };
83 Reference< XMultiComponentFactory > xSMgr_( i_xContext->getServiceManager(), UNO_SET_THROW );
84 // TODO: Ctor
85 Reference< resource::XStringResourceManager > xStringResourceManager( xSMgr_->createInstanceWithContext
86 ( "com.sun.star.resource.StringResourceWithLocation",
87 i_xContext ), UNO_QUERY );
88 if( xStringResourceManager.is() )
90 Reference< XInitialization > xInit( xStringResourceManager, UNO_QUERY );
91 if( xInit.is() )
92 xInit->initialize( aArgs );
94 return xStringResourceManager;
96 Reference< container::XNameContainer > lcl_createControlModel(const Reference< XComponentContext >& i_xContext)
98 Reference< XMultiComponentFactory > xSMgr_( i_xContext->getServiceManager(), UNO_SET_THROW );
99 Reference< container::XNameContainer > xControlModel( xSMgr_->createInstanceWithContext("com.sun.star.awt.UnoControlDialogModel", i_xContext ), UNO_QUERY_THROW );
100 return xControlModel;
102 Reference< container::XNameContainer > lcl_createDialogModel( const Reference< XComponentContext >& i_xContext,
103 const Reference< io::XInputStream >& xInput,
104 const Reference< frame::XModel >& xModel,
105 const Reference< resource::XStringResourceManager >& xStringResourceManager,
106 const Any &aDialogSourceURL)
108 Reference< container::XNameContainer > xDialogModel( lcl_createControlModel(i_xContext) );
110 Reference< beans::XPropertySet > xDlgPropSet( xDialogModel, UNO_QUERY );
111 xDlgPropSet->setPropertyValue( "DialogSourceURL", aDialogSourceURL );
113 // #TODO we really need to detect the source of the Dialog, is it
114 // the dialog. E.g. if the dialog was created from basic ( then we just
115 // can't tell where its from )
116 // If we are happy to always substitute the form model for the awt
117 // one then maybe the presence of a document model is enough to trigger
118 // swapping out the models ( or perhaps we only want to do this
119 // for vba mode ) there are a number of feasible and valid possibilities
120 ::xmlscript::importDialogModel( xInput, xDialogModel, i_xContext, xModel );
122 // Set resource property
123 if( xStringResourceManager.is() )
125 Reference< beans::XPropertySet > xDlgPSet( xDialogModel, UNO_QUERY );
126 Any aStringResourceManagerAny;
127 aStringResourceManagerAny <<= xStringResourceManager;
128 xDlgPSet->setPropertyValue( "ResourceResolver", aStringResourceManagerAny );
131 return xDialogModel;
134 // mutex
137 ::osl::Mutex& getMutex()
139 static ::osl::Mutex s_aMutex;
141 return s_aMutex;
145 // DialogProviderImpl
148 DialogProviderImpl::DialogProviderImpl( const Reference< XComponentContext >& rxContext )
149 :m_xContext( rxContext )
154 DialogProviderImpl::~DialogProviderImpl()
159 static Reference< resource::XStringResourceManager > getStringResourceFromDialogLibrary
160 ( const Reference< container::XNameContainer >& xDialogLib )
162 Reference< resource::XStringResourceManager > xStringResourceManager;
163 if( xDialogLib.is() )
165 Reference< resource::XStringResourceSupplier > xStringResourceSupplier( xDialogLib, UNO_QUERY );
166 if( xStringResourceSupplier.is() )
168 Reference< resource::XStringResourceResolver >
169 xStringResourceResolver = xStringResourceSupplier->getStringResource();
171 xStringResourceManager =
172 Reference< resource::XStringResourceManager >( xStringResourceResolver, UNO_QUERY );
175 return xStringResourceManager;
178 Reference< container::XNameContainer > DialogProviderImpl::createDialogModel(
179 const Reference< io::XInputStream >& xInput,
180 const Reference< resource::XStringResourceManager >& xStringResourceManager,
181 const Any &aDialogSourceURL)
183 return lcl_createDialogModel(m_xContext,xInput,m_xModel,xStringResourceManager,aDialogSourceURL);
186 Reference< XControlModel > DialogProviderImpl::createDialogModelForBasic()
188 if (!m_BasicInfo)
189 // shouldn't get here
190 throw RuntimeException("No information to create dialog" );
191 Reference< resource::XStringResourceManager > xStringResourceManager = getStringResourceFromDialogLibrary( m_BasicInfo->mxDlgLib );
193 Any aDialogSourceURL((OUString()));
194 Reference< XControlModel > xCtrlModel( createDialogModel( m_BasicInfo->mxInput, xStringResourceManager, aDialogSourceURL ), UNO_QUERY_THROW );
195 return xCtrlModel;
198 Reference< XControlModel > DialogProviderImpl::createDialogModel( const OUString& sURL )
201 OUString aURL( sURL );
203 // parse URL
204 // TODO: use URL parsing class
205 // TODO: decoding of location
207 Reference< uri::XUriReferenceFactory > xFac ( uri::UriReferenceFactory::create( m_xContext ) );
209 // i75778: Support non-script URLs
210 Reference< io::XInputStream > xInput;
211 Reference< container::XNameContainer > xDialogLib;
213 // Accept file URL to single dialog
214 bool bSingleDialog = false;
216 Reference< util::XMacroExpander > xMacroExpander =
217 util::theMacroExpander::get(m_xContext);
219 Reference< uri::XUriReference > uriRef;
220 for (;;)
222 uriRef = xFac->parse( aURL );
223 if ( !uriRef.is() )
225 OUString errorMsg = "DialogProviderImpl::getDialogModel: failed to parse URI: " + aURL;
226 throw IllegalArgumentException( errorMsg, Reference< XInterface >(), 1 );
228 Reference < uri::XVndSunStarExpandUrl > sxUri( uriRef, UNO_QUERY );
229 if( !sxUri.is() )
230 break;
232 aURL = sxUri->expand( xMacroExpander );
235 Reference < uri::XVndSunStarScriptUrl > sfUri( uriRef, UNO_QUERY );
236 if( !sfUri.is() )
238 bSingleDialog = true;
240 // Try any other URL with SimpleFileAccess
241 Reference< ucb::XSimpleFileAccess3 > xSFI = ucb::SimpleFileAccess::create(m_xContext);
245 xInput = xSFI->openFileRead( aURL );
247 catch( Exception& )
250 else
252 OUString sDescription = sfUri->getName();
254 sal_Int32 nIndex = 0;
256 OUString sLibName = sDescription.getToken( 0, '.', nIndex );
257 OUString sDlgName;
258 if ( nIndex != -1 )
259 sDlgName = sDescription.getToken( 0, '.', nIndex );
261 OUString sLocation = sfUri->getParameter( "location" );
264 // get dialog library container
265 // TODO: dialogs in packages
266 Reference< XLibraryContainer > xLibContainer;
268 if ( sLocation == "application" )
270 xLibContainer = SfxGetpApp()->GetDialogContainer();
272 else if ( sLocation == "document" )
274 Reference< XEmbeddedScripts > xDocumentScripts( m_xModel, UNO_QUERY );
275 if ( xDocumentScripts.is() )
277 xLibContainer = xDocumentScripts->getDialogLibraries();
278 OSL_ENSURE( xLibContainer.is(),
279 "DialogProviderImpl::createDialogModel: invalid dialog container!" );
282 else
284 const Sequence< OUString > aOpenDocsTdocURLs( MiscUtils::allOpenTDocUrls( m_xContext ) );
285 for ( auto const & tdocURL : aOpenDocsTdocURLs )
287 Reference< frame::XModel > xModel( MiscUtils::tDocUrlToModel( tdocURL ) );
288 OSL_ENSURE( xModel.is(), "DialogProviderImpl::createDialogModel: invalid document model!" );
289 if ( !xModel.is() )
290 continue;
292 OUString sDocURL = xModel->getURL();
293 if ( sDocURL.isEmpty() )
295 sDocURL = ::comphelper::NamedValueCollection::getOrDefault( xModel->getArgs(), u"Title", sDocURL );
298 if ( sLocation != sDocURL )
299 continue;
301 Reference< XEmbeddedScripts > xDocumentScripts( m_xModel, UNO_QUERY );
302 if ( !xDocumentScripts.is() )
303 continue;
305 xLibContainer = xDocumentScripts->getDialogLibraries();
306 OSL_ENSURE( xLibContainer.is(),
307 "DialogProviderImpl::createDialogModel: invalid dialog container!" );
311 // get input stream provider
312 Reference< io::XInputStreamProvider > xISP;
313 if ( !xLibContainer.is() )
315 throw IllegalArgumentException(
316 "DialogProviderImpl::getDialog: library container not found!",
317 Reference< XInterface >(), 1 );
320 // load dialog library
321 if ( !xLibContainer->isLibraryLoaded( sLibName ) )
322 xLibContainer->loadLibrary( sLibName );
324 // get dialog library
325 if ( xLibContainer->hasByName( sLibName ) )
327 Any aElement = xLibContainer->getByName( sLibName );
328 aElement >>= xDialogLib;
331 if ( !xDialogLib.is() )
333 throw IllegalArgumentException(
334 "DialogProviderImpl::getDialogModel: library not found!",
335 Reference< XInterface >(), 1 );
338 // get input stream provider
339 if ( xDialogLib->hasByName( sDlgName ) )
341 Any aElement = xDialogLib->getByName( sDlgName );
342 aElement >>= xISP;
345 if ( !xISP.is() )
347 throw IllegalArgumentException(
348 "DialogProviderImpl::getDialogModel: dialog not found!",
349 Reference< XInterface >(), 1 );
354 if ( xISP.is() )
355 xInput = xISP->createInputStream();
356 msDialogLibName = sLibName;
359 // import dialog model
360 Reference< XControlModel > xCtrlModel;
361 if ( xInput.is() && m_xContext.is() )
363 Reference< resource::XStringResourceManager > xStringResourceManager;
364 if( bSingleDialog )
366 xStringResourceManager = lcl_getStringResourceManager(m_xContext,aURL);
368 else if( xDialogLib.is() )
370 xStringResourceManager = getStringResourceFromDialogLibrary( xDialogLib );
373 Any aDialogSourceURLAny;
374 aDialogSourceURLAny <<= aURL;
376 Reference< container::XNameContainer > xDialogModel( createDialogModel( xInput , xStringResourceManager, aDialogSourceURLAny ), UNO_SET_THROW);
378 xCtrlModel.set( xDialogModel, UNO_QUERY );
380 return xCtrlModel;
384 Reference< XUnoControlDialog > DialogProviderImpl::createDialogControl
385 ( const Reference< XControlModel >& rxDialogModel, const Reference< XWindowPeer >& xParent )
387 OSL_ENSURE( rxDialogModel.is(), "DialogProviderImpl::getDialogControl: no dialog model" );
389 Reference< XUnoControlDialog > xDialogControl;
391 if ( m_xContext.is() )
393 xDialogControl = UnoControlDialog::create( m_xContext );
395 // set the model
396 if ( rxDialogModel.is() )
397 xDialogControl->setModel( rxDialogModel );
399 // set visible
400 xDialogControl->setVisible( false );
402 // get the parent of the dialog control
403 Reference< XWindowPeer > xPeer;
404 if( xParent.is() )
406 xPeer = xParent;
408 else if ( m_xModel.is() )
410 Reference< frame::XController > xController = m_xModel->getCurrentController();
411 if ( xController.is() )
413 Reference< frame::XFrame > xFrame = xController->getFrame();
414 if ( xFrame.is() )
415 xPeer.set( xFrame->getContainerWindow(), UNO_QUERY );
419 // create a peer
420 Reference< XToolkit> xToolkit( Toolkit::create( m_xContext ), UNO_QUERY_THROW );
421 xDialogControl->createPeer( xToolkit, xPeer );
424 return xDialogControl;
428 void DialogProviderImpl::attachControlEvents(
429 const Reference< XControl >& rxControl,
430 const Reference< XInterface >& rxHandler,
431 const Reference< XIntrospectionAccess >& rxIntrospectionAccess,
432 bool bDialogProviderMode )
434 if ( !rxControl.is() )
435 return;
437 Reference< XControlContainer > xControlContainer( rxControl, UNO_QUERY );
439 if ( !xControlContainer.is() )
440 return;
442 Sequence< Reference< XControl > > aControls = xControlContainer->getControls();
443 const Reference< XControl >* pControls = aControls.getConstArray();
444 sal_Int32 nControlCount = aControls.getLength();
446 Sequence< Reference< XInterface > > aObjects( nControlCount + 1 );
447 Reference< XInterface >* pObjects = aObjects.getArray();
448 for ( sal_Int32 i = 0; i < nControlCount; ++i )
450 pObjects[i].set( pControls[i], UNO_QUERY );
453 // also add the dialog control itself to the sequence
454 pObjects[nControlCount].set( rxControl, UNO_QUERY );
456 Reference<XScriptEventsAttacher> xScriptEventsAttacher
457 = new DialogEventsAttacherImpl(
458 m_xContext, m_xModel, rxControl, rxHandler, rxIntrospectionAccess,
459 bDialogProviderMode,
460 (m_BasicInfo ? m_BasicInfo->mxBasicRTLListener : nullptr), msDialogLibName);
462 Any aHelper;
463 xScriptEventsAttacher->attachEvents( aObjects, Reference< XScriptListener >(), aHelper );
466 Reference< XIntrospectionAccess > DialogProviderImpl::inspectHandler( const Reference< XInterface >& rxHandler )
468 Reference< XIntrospectionAccess > xIntrospectionAccess;
469 static Reference< XIntrospection > xIntrospection;
471 if( !rxHandler.is() )
472 return xIntrospectionAccess;
474 if( !xIntrospection.is() )
476 // Get introspection service
477 xIntrospection = theIntrospection::get( m_xContext );
480 // Do introspection
483 Any aHandlerAny;
484 aHandlerAny <<= rxHandler;
485 xIntrospectionAccess = xIntrospection->inspect( aHandlerAny );
487 catch( RuntimeException& )
489 xIntrospectionAccess.clear();
491 return xIntrospectionAccess;
495 // XServiceInfo
498 OUString DialogProviderImpl::getImplementationName( )
500 return "com.sun.star.comp.scripting.DialogProvider";
503 sal_Bool DialogProviderImpl::supportsService( const OUString& rServiceName )
505 return cppu::supportsService(this, rServiceName);
508 Sequence< OUString > DialogProviderImpl::getSupportedServiceNames( )
510 return { "com.sun.star.awt.DialogProvider",
511 "com.sun.star.awt.DialogProvider2",
512 "com.sun.star.awt.ContainerWindowProvider" };
516 // XInitialization
519 void DialogProviderImpl::initialize( const Sequence< Any >& aArguments )
521 ::osl::MutexGuard aGuard( getMutex() );
523 if ( aArguments.getLength() == 1 )
525 aArguments[0] >>= m_xModel;
527 if ( !m_xModel.is() )
529 throw RuntimeException( "DialogProviderImpl::initialize: invalid argument format!" );
532 else if ( aArguments.getLength() == 4 )
534 // call from RTL_Impl_CreateUnoDialog
535 aArguments[0] >>= m_xModel;
536 m_BasicInfo.reset( new BasicRTLParams );
537 m_BasicInfo->mxInput.set( aArguments[ 1 ], UNO_QUERY_THROW );
538 // allow null mxDlgLib, a document dialog instantiated from
539 // from application basic is unable to provide ( or find ) it's
540 // Library
541 aArguments[ 2 ] >>= m_BasicInfo->mxDlgLib;
542 // leave the possibility to optionally allow the old dialog creation
543 // to use the new XScriptListener ( which converts the old style macro
544 // to a SF url )
545 m_BasicInfo->mxBasicRTLListener.set( aArguments[ 3 ], UNO_QUERY);
547 else if ( aArguments.getLength() > 4 )
549 throw RuntimeException( "DialogProviderImpl::initialize: invalid number of arguments!" );
554 // XDialogProvider
557 constexpr OUString aDecorationPropName = u"Decoration"_ustr;
559 Reference < XControl > DialogProviderImpl::createDialogImpl(
560 const OUString& URL, const Reference< XInterface >& xHandler,
561 const Reference< XWindowPeer >& xParent, bool bDialogProviderMode )
563 // if the dialog is located in a document, the document must already be open!
565 ::osl::MutexGuard aGuard( getMutex() );
568 // m_xHandler = xHandler;
570 //Reference< XDialog > xDialog;
571 Reference< XControl > xCtrl;
572 Reference< XControlModel > xCtrlMod;
575 // add support for basic RTL_FUNCTION
576 if (m_BasicInfo)
577 xCtrlMod = createDialogModelForBasic();
578 else
580 OSL_ENSURE( !URL.isEmpty(), "DialogProviderImpl::getDialog: no URL!" );
581 xCtrlMod = createDialogModel( URL );
584 catch ( const RuntimeException& ) { throw; }
585 catch ( const Exception& )
587 const Any aError( ::cppu::getCaughtException() );
588 throw WrappedTargetRuntimeException( OUString(), *this, aError );
590 if ( xCtrlMod.is() )
592 // i83963 Force decoration
593 if( bDialogProviderMode )
595 uno::Reference< beans::XPropertySet > xDlgModPropSet( xCtrlMod, uno::UNO_QUERY );
596 if( xDlgModPropSet.is() )
600 bool bDecoration = true;
601 Any aDecorationAny = xDlgModPropSet->getPropertyValue( aDecorationPropName );
602 aDecorationAny >>= bDecoration;
603 if( !bDecoration )
605 xDlgModPropSet->setPropertyValue( aDecorationPropName, Any( true ) );
606 xDlgModPropSet->setPropertyValue( "Title", Any( OUString() ) );
609 catch( UnknownPropertyException& )
614 xCtrl.set( createDialogControl( xCtrlMod, xParent ) );
615 if ( xCtrl.is() )
617 Reference< XIntrospectionAccess > xIntrospectionAccess = inspectHandler( xHandler );
618 attachControlEvents( xCtrl, xHandler, xIntrospectionAccess, bDialogProviderMode );
622 return xCtrl;
625 Reference < XDialog > DialogProviderImpl::createDialog( const OUString& URL )
627 Reference< XInterface > xDummyHandler;
628 Reference< XWindowPeer > xDummyPeer;
629 Reference < XControl > xControl = DialogProviderImpl::createDialogImpl( URL, xDummyHandler, xDummyPeer, true );
630 Reference< XDialog > xDialog( xControl, UNO_QUERY );
631 return xDialog;
634 Reference < XDialog > DialogProviderImpl::createDialogWithHandler(
635 const OUString& URL, const Reference< XInterface >& xHandler )
637 if( !xHandler.is() )
639 throw IllegalArgumentException(
640 "DialogProviderImpl::createDialogWithHandler: Invalid xHandler!",
641 Reference< XInterface >(), 1 );
643 Reference< XWindowPeer > xDummyPeer;
644 Reference < XControl > xControl = DialogProviderImpl::createDialogImpl( URL, xHandler, xDummyPeer, true );
645 Reference< XDialog > xDialog( xControl, UNO_QUERY );
646 return xDialog;
649 Reference < XDialog > DialogProviderImpl::createDialogWithArguments(
650 const OUString& URL, const Sequence< NamedValue >& Arguments )
652 ::comphelper::NamedValueCollection aArguments( Arguments );
654 Reference< XWindowPeer > xParentPeer;
655 if ( aArguments.has( "ParentWindow" ) )
657 const Any& aParentWindow( aArguments.get( "ParentWindow" ) );
658 if ( !( aParentWindow >>= xParentPeer ) )
660 const Reference< XControl > xParentControl( aParentWindow, UNO_QUERY );
661 if ( xParentControl.is() )
662 xParentPeer = xParentControl->getPeer();
666 const Reference< XInterface > xHandler( aArguments.get( "EventHandler" ), UNO_QUERY );
668 Reference < XControl > xControl = DialogProviderImpl::createDialogImpl( URL, xHandler, xParentPeer, true );
669 Reference< XDialog > xDialog( xControl, UNO_QUERY );
670 return xDialog;
673 Reference< XWindow > DialogProviderImpl::createContainerWindow(
674 const OUString& URL, const OUString&,
675 const Reference< XWindowPeer >& xParent, const Reference< XInterface >& xHandler )
677 if( !xParent.is() )
679 throw IllegalArgumentException(
680 "DialogProviderImpl::createContainerWindow: Invalid xParent!",
681 Reference< XInterface >(), 1 );
683 Reference < XControl > xControl = DialogProviderImpl::createDialogImpl( URL, xHandler, xParent, false );
684 Reference< XWindow> xWindow( xControl, UNO_QUERY );
685 return xWindow;
689 // component operations
692 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
693 scripting_DialogProviderImpl_get_implementation(
694 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
696 return cppu::acquire(new DialogProviderImpl(context));
699 } // namespace dlgprov
702 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */