1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
;
58 using namespace script
;
59 using namespace beans
;
60 using namespace document
;
61 using namespace ::sf_misc
;
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
83 Reference
< XMultiComponentFactory
> xSMgr_( i_xContext
->getServiceManager(), UNO_SET_THROW
);
85 Reference
< resource::XStringResourceManager
> xStringResourceManager( xSMgr_
->createInstanceWithContext
86 ( u
"com.sun.star.resource.StringResourceWithLocation"_ustr
,
87 i_xContext
), UNO_QUERY
);
88 if( xStringResourceManager
.is() )
90 Reference
< XInitialization
> xInit( xStringResourceManager
, UNO_QUERY
);
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(u
"com.sun.star.awt.UnoControlDialogModel"_ustr
, 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( u
"DialogSourceURL"_ustr
, 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( u
"ResourceResolver"_ustr
, aStringResourceManagerAny
);
137 ::osl::Mutex
& getMutex()
139 static ::osl::Mutex 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()
189 // shouldn't get here
190 throw RuntimeException(u
"No information to create dialog"_ustr
);
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
);
198 Reference
< XControlModel
> DialogProviderImpl::createDialogModel( const OUString
& sURL
)
201 OUString
aURL( sURL
);
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
;
222 uriRef
= xFac
->parse( aURL
);
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
);
232 aURL
= sxUri
->expand( xMacroExpander
);
235 Reference
< uri::XVndSunStarScriptUrl
> sfUri( uriRef
, UNO_QUERY
);
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
);
252 OUString sDescription
= sfUri
->getName();
254 sal_Int32 nIndex
= 0;
256 OUString sLibName
= sDescription
.getToken( 0, '.', nIndex
);
259 sDlgName
= sDescription
.getToken( 0, '.', nIndex
);
261 OUString sLocation
= sfUri
->getParameter( u
"location"_ustr
);
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!" );
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!" );
292 OUString sDocURL
= xModel
->getURL();
293 if ( sDocURL
.isEmpty() )
295 sDocURL
= ::comphelper::NamedValueCollection::getOrDefault( xModel
->getArgs(), u
"Title", sDocURL
);
298 if ( sLocation
!= sDocURL
)
301 Reference
< XEmbeddedScripts
> xDocumentScripts( m_xModel
, UNO_QUERY
);
302 if ( !xDocumentScripts
.is() )
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 u
"DialogProviderImpl::getDialog: library container not found!"_ustr
,
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 u
"DialogProviderImpl::getDialogModel: library not found!"_ustr
,
335 Reference
< XInterface
>(), 1 );
338 // get input stream provider
339 if ( xDialogLib
->hasByName( sDlgName
) )
341 Any aElement
= xDialogLib
->getByName( sDlgName
);
347 throw IllegalArgumentException(
348 u
"DialogProviderImpl::getDialogModel: dialog not found!"_ustr
,
349 Reference
< XInterface
>(), 1 );
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
;
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
);
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
);
396 if ( rxDialogModel
.is() )
397 xDialogControl
->setModel( rxDialogModel
);
400 xDialogControl
->setVisible( false );
402 // get the parent of the dialog control
403 Reference
< XWindowPeer
> xPeer
;
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();
415 xPeer
.set( xFrame
->getContainerWindow(), UNO_QUERY
);
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() )
437 Reference
< XControlContainer
> xControlContainer( rxControl
, UNO_QUERY
);
439 if ( !xControlContainer
.is() )
442 Sequence
< Reference
< XControl
> > aControls
= xControlContainer
->getControls();
443 sal_Int32 nControlCount
= aControls
.getLength();
445 Sequence
< Reference
< XInterface
> > aObjects( nControlCount
+ 1 );
446 Reference
< XInterface
>* pObjects
= aObjects
.getArray();
447 std::transform(aControls
.begin(), aControls
.end(), pObjects
,
448 [](auto& xControl
) { return xControl
.template query
<XInterface
>(); });
450 // also add the dialog control itself to the sequence
451 pObjects
[nControlCount
].set( rxControl
, UNO_QUERY
);
453 Reference
<XScriptEventsAttacher
> xScriptEventsAttacher
454 = new DialogEventsAttacherImpl(
455 m_xContext
, m_xModel
, rxControl
, rxHandler
, rxIntrospectionAccess
,
457 (m_BasicInfo
? m_BasicInfo
->mxBasicRTLListener
: nullptr), msDialogLibName
);
460 xScriptEventsAttacher
->attachEvents( aObjects
, Reference
< XScriptListener
>(), aHelper
);
463 Reference
< XIntrospectionAccess
> DialogProviderImpl::inspectHandler( const Reference
< XInterface
>& rxHandler
)
465 Reference
< XIntrospectionAccess
> xIntrospectionAccess
;
466 static Reference
< XIntrospection
> xIntrospection
;
468 if( !rxHandler
.is() )
469 return xIntrospectionAccess
;
471 if( !xIntrospection
.is() )
473 // Get introspection service
474 xIntrospection
= theIntrospection::get( m_xContext
);
481 aHandlerAny
<<= rxHandler
;
482 xIntrospectionAccess
= xIntrospection
->inspect( aHandlerAny
);
484 catch( RuntimeException
& )
486 xIntrospectionAccess
.clear();
488 return xIntrospectionAccess
;
495 OUString
DialogProviderImpl::getImplementationName( )
497 return u
"com.sun.star.comp.scripting.DialogProvider"_ustr
;
500 sal_Bool
DialogProviderImpl::supportsService( const OUString
& rServiceName
)
502 return cppu::supportsService(this, rServiceName
);
505 Sequence
< OUString
> DialogProviderImpl::getSupportedServiceNames( )
507 return { u
"com.sun.star.awt.DialogProvider"_ustr
,
508 u
"com.sun.star.awt.DialogProvider2"_ustr
,
509 u
"com.sun.star.awt.ContainerWindowProvider"_ustr
};
516 void DialogProviderImpl::initialize( const Sequence
< Any
>& aArguments
)
518 ::osl::MutexGuard
aGuard( getMutex() );
520 if ( aArguments
.getLength() == 1 )
522 aArguments
[0] >>= m_xModel
;
524 if ( !m_xModel
.is() )
526 throw RuntimeException( u
"DialogProviderImpl::initialize: invalid argument format!"_ustr
);
529 else if ( aArguments
.getLength() == 4 )
531 // call from RTL_Impl_CreateUnoDialog
532 aArguments
[0] >>= m_xModel
;
533 m_BasicInfo
.reset( new BasicRTLParams
);
534 m_BasicInfo
->mxInput
.set( aArguments
[ 1 ], UNO_QUERY_THROW
);
535 // allow null mxDlgLib, a document dialog instantiated from
536 // from application basic is unable to provide ( or find ) it's
538 aArguments
[ 2 ] >>= m_BasicInfo
->mxDlgLib
;
539 // leave the possibility to optionally allow the old dialog creation
540 // to use the new XScriptListener ( which converts the old style macro
542 m_BasicInfo
->mxBasicRTLListener
.set( aArguments
[ 3 ], UNO_QUERY
);
544 else if ( aArguments
.getLength() > 4 )
546 throw RuntimeException( u
"DialogProviderImpl::initialize: invalid number of arguments!"_ustr
);
554 constexpr OUString aDecorationPropName
= u
"Decoration"_ustr
;
556 Reference
< XControl
> DialogProviderImpl::createDialogImpl(
557 const OUString
& URL
, const Reference
< XInterface
>& xHandler
,
558 const Reference
< XWindowPeer
>& xParent
, bool bDialogProviderMode
)
560 // if the dialog is located in a document, the document must already be open!
562 ::osl::MutexGuard
aGuard( getMutex() );
565 // m_xHandler = xHandler;
567 //Reference< XDialog > xDialog;
568 Reference
< XControl
> xCtrl
;
569 Reference
< XControlModel
> xCtrlMod
;
572 // add support for basic RTL_FUNCTION
574 xCtrlMod
= createDialogModelForBasic();
577 OSL_ENSURE( !URL
.isEmpty(), "DialogProviderImpl::getDialog: no URL!" );
578 xCtrlMod
= createDialogModel( URL
);
581 catch ( const RuntimeException
& ) { throw; }
582 catch ( const Exception
& )
584 const Any
aError( ::cppu::getCaughtException() );
585 throw WrappedTargetRuntimeException( OUString(), *this, aError
);
589 // i83963 Force decoration
590 if( bDialogProviderMode
)
592 uno::Reference
< beans::XPropertySet
> xDlgModPropSet( xCtrlMod
, uno::UNO_QUERY
);
593 if( xDlgModPropSet
.is() )
597 bool bDecoration
= true;
598 Any aDecorationAny
= xDlgModPropSet
->getPropertyValue( aDecorationPropName
);
599 aDecorationAny
>>= bDecoration
;
602 xDlgModPropSet
->setPropertyValue( aDecorationPropName
, Any( true ) );
603 xDlgModPropSet
->setPropertyValue( u
"Title"_ustr
, Any( OUString() ) );
606 catch( UnknownPropertyException
& )
611 xCtrl
.set( createDialogControl( xCtrlMod
, xParent
) );
614 Reference
< XIntrospectionAccess
> xIntrospectionAccess
= inspectHandler( xHandler
);
615 attachControlEvents( xCtrl
, xHandler
, xIntrospectionAccess
, bDialogProviderMode
);
622 Reference
< XDialog
> DialogProviderImpl::createDialog( const OUString
& URL
)
624 Reference
< XInterface
> xDummyHandler
;
625 Reference
< XWindowPeer
> xDummyPeer
;
626 Reference
< XControl
> xControl
= DialogProviderImpl::createDialogImpl( URL
, xDummyHandler
, xDummyPeer
, true );
627 Reference
< XDialog
> xDialog( xControl
, UNO_QUERY
);
631 Reference
< XDialog
> DialogProviderImpl::createDialogWithHandler(
632 const OUString
& URL
, const Reference
< XInterface
>& xHandler
)
636 throw IllegalArgumentException(
637 u
"DialogProviderImpl::createDialogWithHandler: Invalid xHandler!"_ustr
,
638 Reference
< XInterface
>(), 1 );
640 Reference
< XWindowPeer
> xDummyPeer
;
641 Reference
< XControl
> xControl
= DialogProviderImpl::createDialogImpl( URL
, xHandler
, xDummyPeer
, true );
642 Reference
< XDialog
> xDialog( xControl
, UNO_QUERY
);
646 Reference
< XDialog
> DialogProviderImpl::createDialogWithArguments(
647 const OUString
& URL
, const Sequence
< NamedValue
>& Arguments
)
649 ::comphelper::NamedValueCollection
aArguments( Arguments
);
651 Reference
< XWindowPeer
> xParentPeer
;
652 if ( aArguments
.has( u
"ParentWindow"_ustr
) )
654 const Any
& aParentWindow( aArguments
.get( u
"ParentWindow"_ustr
) );
655 if ( !( aParentWindow
>>= xParentPeer
) )
657 const Reference
< XControl
> xParentControl( aParentWindow
, UNO_QUERY
);
658 if ( xParentControl
.is() )
659 xParentPeer
= xParentControl
->getPeer();
663 const Reference
< XInterface
> xHandler( aArguments
.get( u
"EventHandler"_ustr
), UNO_QUERY
);
665 Reference
< XControl
> xControl
= DialogProviderImpl::createDialogImpl( URL
, xHandler
, xParentPeer
, true );
666 Reference
< XDialog
> xDialog( xControl
, UNO_QUERY
);
670 Reference
< XWindow
> DialogProviderImpl::createContainerWindow(
671 const OUString
& URL
, const OUString
&,
672 const Reference
< XWindowPeer
>& xParent
, const Reference
< XInterface
>& xHandler
)
676 throw IllegalArgumentException(
677 u
"DialogProviderImpl::createContainerWindow: Invalid xParent!"_ustr
,
678 Reference
< XInterface
>(), 1 );
680 Reference
< XControl
> xControl
= DialogProviderImpl::createDialogImpl( URL
, xHandler
, xParent
, false );
681 Reference
< XWindow
> xWindow( xControl
, UNO_QUERY
);
686 // component operations
689 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
690 scripting_DialogProviderImpl_get_implementation(
691 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const&)
693 return cppu::acquire(new DialogProviderImpl(context
));
696 } // namespace dlgprov
699 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */