Files
loongoffice/basctl/source/basicide/scriptdocument.cxx
Jim Raykowski 55e86edcb3 tdf#120658 - Reworking of dialogues Organize macros
(make from 5 existing only one)

Much of what makes up this patch is adapted from existing code that is
used to organize and select macros and to assign macros to shortcut
keys. Comments in the patch say where code is borrowed from.

Known issues:

+ Scripting framework library rename for BeanShell, Java, and JavaScript
always returns fail when there are no macro entries in the library even
though it actually succeeds. The same thing happens using
SvxScriptOrgDialog::renameEntry.

+ Deleting Basic macros from the Macro Manager dialog is not implemented
yet.

Change-Id: If4da04549f8b39675910cbbd1f94dd9a6b73c31a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176254
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2024-12-02 07:13:00 +01:00

1506 lines
51 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <memory>
#include <basctl/scriptdocument.hxx>
#include <basobj.hxx>
#include <strings.hrc>
#include <iderid.hxx>
#include <dlgeddef.hxx>
#include <doceventnotifier.hxx>
#include "documentenumeration.hxx"
#include <com/sun/star/ucb/ContentCreationException.hpp>
#include <com/sun/star/uri/UriReferenceFactory.hpp>
#include <com/sun/star/util/theMacroExpander.hpp>
#include <com/sun/star/frame/XStorable.hpp>
#include <com/sun/star/frame/FrameSearchFlag.hpp>
#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <com/sun/star/awt/XWindow2.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/document/XEmbeddedScripts.hpp>
#include <com/sun/star/script/vba/XVBACompatibility.hpp>
#include <com/sun/star/script/vba/XVBAModuleInfo.hpp>
#include <com/sun/star/script/ModuleInfo.hpp>
#include <com/sun/star/script/ModuleType.hpp>
#include <sfx2/app.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/docfile.hxx>
#include <basic/basicmanagerrepository.hxx>
#include <xmlscript/xmldlg_imexp.hxx>
#include <i18nlangtag/languagetag.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <config_folders.h>
#include <tools/debug.hxx>
#include <comphelper/documentinfo.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/propertysequence.hxx>
#include <comphelper/string.hxx>
#include <vcl/svapp.hxx>
#include <vcl/settings.hxx>
#include <osl/file.hxx>
#include <rtl/uri.hxx>
#include <set>
namespace basctl
{
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::frame::XModel;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::script::XLibraryContainer;
using ::com::sun::star::uno::UNO_QUERY_THROW;
using ::com::sun::star::uno::UNO_SET_THROW;
using ::com::sun::star::uno::Exception;
using ::com::sun::star::container::XNameContainer;
using ::com::sun::star::container::NoSuchElementException;
using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::task::XStatusIndicator;
using ::com::sun::star::uno::Any;
using ::com::sun::star::script::XLibraryContainer2;
using ::com::sun::star::uri::UriReferenceFactory;
using ::com::sun::star::uri::XUriReferenceFactory;
using ::com::sun::star::uri::XUriReference;
using ::com::sun::star::uno::XComponentContext;
using ::com::sun::star::util::XMacroExpander;
using ::com::sun::star::util::theMacroExpander;
using ::com::sun::star::io::XInputStreamProvider;
using ::com::sun::star::uno::Any;
using ::com::sun::star::io::XInputStream;
using ::com::sun::star::frame::XStorable;
using ::com::sun::star::util::XModifiable;
using ::com::sun::star::frame::XController;
using ::com::sun::star::frame::XFrame;
using ::com::sun::star::util::URL;
using ::com::sun::star::frame::XDispatchProvider;
using ::com::sun::star::frame::XDispatch;
using ::com::sun::star::beans::PropertyValue;
using ::com::sun::star::awt::XWindow2;
using ::com::sun::star::document::XEmbeddedScripts;
using ::com::sun::star::script::ModuleInfo;
using ::com::sun::star::script::vba::XVBACompatibility;
using ::com::sun::star::script::vba::XVBAModuleInfo;
namespace FrameSearchFlag = ::com::sun::star::frame::FrameSearchFlag;
namespace
{
class FilterDocuments : public docs::IDocumentDescriptorFilter
{
public:
explicit FilterDocuments(bool _bFilterInvisible)
: m_bFilterInvisible(_bFilterInvisible)
{
}
virtual ~FilterDocuments() {}
virtual bool includeDocument( const docs::DocumentDescriptor& _rDocument ) const override;
private:
static bool impl_isDocumentVisible_nothrow( const docs::DocumentDescriptor& _rDocument );
private:
bool m_bFilterInvisible;
};
bool FilterDocuments::impl_isDocumentVisible_nothrow( const docs::DocumentDescriptor& _rDocument )
{
try
{
for (auto const& controller : _rDocument.aControllers)
{
Reference< XFrame > xFrame( controller->getFrame(), UNO_SET_THROW );
Reference< XWindow2 > xContainer( xFrame->getContainerWindow(), UNO_QUERY_THROW );
if ( xContainer->isVisible() )
return true;
}
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
return false;
}
bool FilterDocuments::includeDocument( const docs::DocumentDescriptor& _rDocument ) const
{
Reference< XEmbeddedScripts > xScripts( _rDocument.xModel, UNO_QUERY );
if ( !xScripts.is() )
return false;
return !m_bFilterInvisible || impl_isDocumentVisible_nothrow( _rDocument );
}
void lcl_getAllModels_throw( docs::Documents& _out_rModels, bool _bVisibleOnly )
{
_out_rModels.clear();
FilterDocuments aFilter( _bVisibleOnly );
docs::DocumentEnumeration aEnum(
comphelper::getProcessComponentContext(), &aFilter );
aEnum.getDocuments( _out_rModels );
}
}
class ScriptDocument::Impl : public DocumentEventListener
{
private:
bool m_bIsApplication;
bool m_bValid;
bool m_bDocumentClosed;
Reference< XModel > m_xDocument;
Reference< XModifiable > m_xDocModify;
Reference< XEmbeddedScripts > m_xScriptAccess;
std::unique_ptr< DocumentEventNotifier > m_pDocListener;
public:
Impl ();
explicit Impl(Reference<XModel> const& rxDocument);
virtual ~Impl() override;
/** determines whether the instance refers to a valid "document" with script and
dialog libraries
*/
bool isValid() const { return m_bValid; }
/** determines whether the instance refers to a non-closed document
*/
bool isAlive() const { return m_bValid && ( m_bIsApplication || !m_bDocumentClosed ); }
/// determines whether the "document" refers to the application in real
bool isApplication() const { return m_bValid && m_bIsApplication; }
/// determines whether the document refers to a real document (instead of the application)
bool isDocument() const { return m_bValid && !m_bIsApplication; }
/** invalidates the instance
*/
void invalidate();
const Reference< XModel >&
getDocumentRef() const { return m_xDocument; }
/// returns a library container belonging to the document
Reference< XLibraryContainer >
getLibraryContainer( LibraryContainerType _eType ) const;
/// determines whether a given library is part of the shared installation
bool isLibraryShared( const OUString& _rLibName, LibraryContainerType _eType );
/** returns the current frame of the document
To be called for documents only, not for the application.
If <FALSE/> is returned, an assertion will be raised in non-product builds.
*/
bool getCurrentFrame( Reference< XFrame >& _out_rxFrame ) const;
// versions with the same signature/semantics as in ScriptDocument itself
bool isReadOnly() const;
bool isInVBAMode() const;
BasicManager*
getBasicManager() const;
Reference< XModel >
getDocument() const;
void setDocumentModified() const;
bool isDocumentModified() const;
void saveDocument( const Reference< XStatusIndicator >& _rxStatusIndicator ) const;
OUString getTitle() const;
OUString getURL() const;
bool allowMacros() const;
Reference< XNameContainer >
getLibrary( LibraryContainerType _eType, const OUString& _rLibName, bool _bLoadLibrary ) const;
bool hasLibrary( LibraryContainerType _eType, const OUString& _rLibName ) const;
Reference< XNameContainer >
getOrCreateLibrary( LibraryContainerType _eType, const OUString& _rLibName ) const;
void loadLibraryIfExists( LibraryContainerType _eType, const OUString& _rLibrary );
bool removeModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rModuleName );
bool hasModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rModName ) const;
bool getModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rObjectName, Any& _out_rModuleOrDialog );
bool renameModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rOldName, const OUString& _rNewName, const Reference< XNameContainer >& _rxExistingDialogModel );
bool createModule( const OUString& _rLibName, const OUString& _rModName, bool _bCreateMain, OUString& _out_rNewModuleCode ) const;
bool insertModuleOrDialog( LibraryContainerType _eType, const OUString& _rObjectName, const OUString& _rModName, const Any& _rElement ) const;
bool updateModule( const OUString& _rLibName, const OUString& _rModName, const OUString& _rModuleCode ) const;
bool createDialog( const OUString& _rLibName, const OUString& _rDialogName, Reference< XInputStreamProvider >& _out_rDialogProvider ) const;
protected:
// DocumentEventListener
virtual void onDocumentCreated( const ScriptDocument& _rDocument ) override;
virtual void onDocumentOpened( const ScriptDocument& _rDocument ) override;
virtual void onDocumentSave( const ScriptDocument& _rDocument ) override;
virtual void onDocumentSaveDone( const ScriptDocument& _rDocument ) override;
virtual void onDocumentSaveAs( const ScriptDocument& _rDocument ) override;
virtual void onDocumentSaveAsDone( const ScriptDocument& _rDocument ) override;
virtual void onDocumentClosed( const ScriptDocument& _rDocument ) override;
virtual void onDocumentTitleChanged( const ScriptDocument& _rDocument ) override;
virtual void onDocumentModeChanged( const ScriptDocument& _rDocument ) override;
private:
bool impl_initDocument_nothrow( const Reference< XModel >& _rxModel );
};
ScriptDocument::Impl::Impl()
:m_bIsApplication( true )
,m_bValid( true )
,m_bDocumentClosed( false )
{
}
ScriptDocument::Impl::Impl( const Reference< XModel >& _rxDocument )
:m_bIsApplication( false )
,m_bValid( false )
,m_bDocumentClosed( false )
{
if ( _rxDocument.is() )
impl_initDocument_nothrow( _rxDocument );
}
ScriptDocument::Impl::~Impl()
{
invalidate();
}
void ScriptDocument::Impl::invalidate()
{
m_bIsApplication = false;
m_bValid = false;
m_bDocumentClosed = false;
m_xDocument.clear();
m_xDocModify.clear();
m_xScriptAccess.clear();
if (m_pDocListener)
m_pDocListener->dispose();
}
bool ScriptDocument::Impl::impl_initDocument_nothrow( const Reference< XModel >& _rxModel )
{
try
{
m_xDocument.set ( _rxModel, UNO_SET_THROW );
m_xDocModify.set ( _rxModel, UNO_QUERY_THROW );
m_xScriptAccess.set ( _rxModel, UNO_QUERY );
m_bValid = m_xScriptAccess.is();
if ( m_bValid )
m_pDocListener.reset( new DocumentEventNotifier( *this, _rxModel ) );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
m_bValid = false;
}
if ( !m_bValid )
{
invalidate();
}
return m_bValid;
}
Reference< XLibraryContainer > ScriptDocument::Impl::getLibraryContainer( LibraryContainerType _eType ) const
{
OSL_ENSURE( isValid(), "ScriptDocument::Impl::getLibraryContainer: invalid!" );
Reference< XLibraryContainer > xContainer;
if ( !isValid() )
return xContainer;
try
{
if ( isApplication() )
xContainer.set( _eType == E_SCRIPTS ? SfxGetpApp()->GetBasicContainer() : SfxGetpApp()->GetDialogContainer(), UNO_QUERY_THROW );
else
{
xContainer.set(
_eType == E_SCRIPTS ? m_xScriptAccess->getBasicLibraries() : m_xScriptAccess->getDialogLibraries(),
UNO_QUERY_THROW );
}
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
return xContainer;
}
bool ScriptDocument::Impl::isReadOnly() const
{
OSL_ENSURE( isValid(), "ScriptDocument::Impl::isReadOnly: invalid state!" );
OSL_ENSURE( !isApplication(), "ScriptDocument::Impl::isReadOnly: not allowed to be called for the application!" );
bool bIsReadOnly = true;
if ( isValid() && !isApplication() )
{
try
{
// note that XStorable is required by the OfficeDocument service
Reference< XStorable > xDocStorable( m_xDocument, UNO_QUERY_THROW );
bIsReadOnly = xDocStorable->isReadonly();
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
}
return bIsReadOnly;
}
bool ScriptDocument::Impl::isInVBAMode() const
{
bool bResult = false;
if ( !isApplication() )
{
Reference< XVBACompatibility > xVBACompat( getLibraryContainer( E_SCRIPTS ), UNO_QUERY );
if ( xVBACompat.is() )
bResult = xVBACompat->getVBACompatibilityMode();
}
return bResult;
}
BasicManager* ScriptDocument::Impl::getBasicManager() const
{
try
{
OSL_ENSURE( isValid(), "ScriptDocument::Impl::getBasicManager: invalid state!" );
if ( !isValid() )
return nullptr;
if ( isApplication() )
return SfxApplication::GetBasicManager();
return ::basic::BasicManagerRepository::getDocumentBasicManager( m_xDocument );
}
catch (const css::ucb::ContentCreationException&)
{
TOOLS_WARN_EXCEPTION( "basctl.basicide", "ScriptDocument::getBasicManager" );
}
return nullptr;
}
Reference< XModel > ScriptDocument::Impl::getDocument() const
{
OSL_ENSURE( isValid(), "ScriptDocument::Impl::getDocument: invalid state!" );
OSL_ENSURE( isDocument(), "ScriptDocument::Impl::getDocument: for documents only!" );
if ( !isValid() || !isDocument() )
return nullptr;
return m_xDocument;
}
Reference< XNameContainer > ScriptDocument::Impl::getLibrary( LibraryContainerType _eType, const OUString& _rLibName, bool _bLoadLibrary ) const
{
OSL_ENSURE( isValid(), "ScriptDocument::Impl::getLibrary: invalid state!" );
Reference< XNameContainer > xContainer;
try
{
Reference< XLibraryContainer > xLibContainer = getLibraryContainer( _eType );
if ( isValid() && xLibContainer.is() )
xContainer.set( xLibContainer->getByName( _rLibName ), UNO_QUERY_THROW );
if ( !xContainer.is() )
throw NoSuchElementException();
// load library
if ( _bLoadLibrary && !xLibContainer->isLibraryLoaded( _rLibName ) )
xLibContainer->loadLibrary( _rLibName );
}
catch( const NoSuchElementException& )
{
throw; // allowed to leave
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
return xContainer;
}
bool ScriptDocument::Impl::hasLibrary( LibraryContainerType _eType, const OUString& _rLibName ) const
{
bool bHas = false;
try
{
Reference< XLibraryContainer > xLibContainer = getLibraryContainer( _eType );
bHas = xLibContainer.is() && xLibContainer->hasByName( _rLibName );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
return bHas;
}
Reference< XNameContainer > ScriptDocument::Impl::getOrCreateLibrary( LibraryContainerType _eType, const OUString& _rLibName ) const
{
Reference< XNameContainer > xLibrary;
try
{
Reference< XLibraryContainer > xLibContainer( getLibraryContainer( _eType ), UNO_SET_THROW );
if ( xLibContainer->hasByName( _rLibName ) )
xLibrary.set( xLibContainer->getByName( _rLibName ), UNO_QUERY_THROW );
else
xLibrary.set( xLibContainer->createLibrary( _rLibName ), UNO_SET_THROW );
if ( !xLibContainer->isLibraryLoaded( _rLibName ) )
xLibContainer->loadLibrary( _rLibName );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
return xLibrary;
}
void ScriptDocument::Impl::loadLibraryIfExists( LibraryContainerType _eType, const OUString& _rLibrary )
{
try
{
Reference< XLibraryContainer > xLibContainer( getLibraryContainer( _eType ) );
if ( xLibContainer.is() && xLibContainer->hasByName( _rLibrary ) && !xLibContainer->isLibraryLoaded( _rLibrary ) )
xLibContainer->loadLibrary( _rLibrary );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
}
bool ScriptDocument::Impl::removeModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rModuleName )
{
OSL_ENSURE( isValid(), "ScriptDocument::Impl::removeModuleOrDialog: invalid!" );
if ( !isValid() )
return false;
try
{
Reference< XNameContainer > xLib( getLibrary( _eType, _rLibName, true ) );
if ( xLib.is() )
{
xLib->removeByName( _rModuleName );
Reference< XVBAModuleInfo > xVBAModuleInfo(xLib, UNO_QUERY);
if(xVBAModuleInfo.is() && xVBAModuleInfo->hasModuleInfo(_rModuleName))
xVBAModuleInfo->removeModuleInfo(_rModuleName);
return true;
}
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
return false;
}
bool ScriptDocument::Impl::hasModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rModName ) const
{
OSL_ENSURE( isValid(), "ScriptDocument::Impl::hasModuleOrDialog: invalid!" );
if ( !isValid() )
return false;
try
{
Reference< XNameContainer > xLib( getLibrary( _eType, _rLibName, true ) );
if ( xLib.is() )
return xLib->hasByName( _rModName );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
return false;
}
bool ScriptDocument::Impl::getModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rObjectName, Any& _out_rModuleOrDialog )
{
OSL_ENSURE( isValid(), "ScriptDocument::Impl::getModuleOrDialog: invalid!" );
if ( !isValid() )
return false;
_out_rModuleOrDialog.clear();
try
{
Reference< XNameContainer > xLib( getLibrary( _eType, _rLibName, true ), UNO_SET_THROW );
if ( xLib->hasByName( _rObjectName ) )
{
_out_rModuleOrDialog = xLib->getByName( _rObjectName );
return true;
}
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
return false;
}
bool ScriptDocument::Impl::renameModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName,
const OUString& _rOldName, const OUString& _rNewName, const Reference< XNameContainer >& _rxExistingDialogModel )
{
OSL_ENSURE( isValid(), "ScriptDocument::Impl::renameModuleOrDialog: invalid!" );
if ( !isValid() )
return false;
try
{
Reference< XNameContainer > xLib( getLibrary( _eType, _rLibName, true ), UNO_SET_THROW );
// get element
Any aElement( xLib->getByName( _rOldName ) );
// remove element from container
xLib->removeByName( _rOldName );
// if it's a dialog, import and export, to reflect the new name
if ( _eType == E_DIALOGS )
{
// create dialog model
const Reference< XComponentContext >& aContext(
comphelper::getProcessComponentContext() );
Reference< XNameContainer > xDialogModel;
if ( _rxExistingDialogModel.is() )
xDialogModel = _rxExistingDialogModel;
else
xDialogModel.set(
( aContext->getServiceManager()->
createInstanceWithContext(
u"com.sun.star.awt.UnoControlDialogModel"_ustr,
aContext ) ),
UNO_QUERY_THROW );
// import dialog model
Reference< XInputStreamProvider > xISP( aElement, UNO_QUERY_THROW );
if ( !_rxExistingDialogModel.is() )
{
Reference< XInputStream > xInput( xISP->createInputStream(), UNO_SET_THROW );
::xmlscript::importDialogModel( xInput, xDialogModel, aContext, isDocument() ? getDocument() : Reference< XModel >() );
}
// set new name as property
Reference< XPropertySet > xDlgPSet( xDialogModel, UNO_QUERY_THROW );
xDlgPSet->setPropertyValue( DLGED_PROP_NAME, Any( _rNewName ) );
// export dialog model
xISP = ::xmlscript::exportDialogModel( xDialogModel, aContext, isDocument() ? getDocument() : Reference< XModel >() );
aElement <<= xISP;
}
// insert element by new name in container
if ( _eType == E_SCRIPTS )
{
Reference< XVBAModuleInfo > xVBAModuleInfo( xLib, UNO_QUERY );
if ( xVBAModuleInfo.is() && xVBAModuleInfo->hasModuleInfo( _rOldName ) )
{
ModuleInfo sModuleInfo = xVBAModuleInfo->getModuleInfo( _rOldName );
xVBAModuleInfo->removeModuleInfo( _rOldName );
xVBAModuleInfo->insertModuleInfo( _rNewName, sModuleInfo );
}
}
xLib->insertByName( _rNewName, aElement );
return true;
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
return false;
}
bool ScriptDocument::Impl::createModule( const OUString& _rLibName, const OUString& _rModName, bool _bCreateMain, OUString& _out_rNewModuleCode ) const
{
_out_rNewModuleCode.clear();
try
{
Reference< XNameContainer > xLib( getLibrary( E_SCRIPTS, _rLibName, true ) );
if ( !xLib.is() || xLib->hasByName( _rModName ) )
return false;
// create new module
_out_rNewModuleCode = "REM ***** BASIC *****\n\n" ;
if ( _bCreateMain )
_out_rNewModuleCode += "Sub Main\n\nEnd Sub\n" ;
Reference< XVBAModuleInfo > xVBAModuleInfo(xLib, UNO_QUERY);
if (xVBAModuleInfo.is())
{
css::script::ModuleInfo aModuleInfo;
aModuleInfo.ModuleType = css::script::ModuleType::NORMAL;
xVBAModuleInfo->insertModuleInfo(_rModName, aModuleInfo);
}
// insert module into library
xLib->insertByName( _rModName, Any( _out_rNewModuleCode ) );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
return false;
}
return true;
}
bool ScriptDocument::Impl::insertModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rObjectName, const Any& _rElement ) const
{
try
{
Reference< XNameContainer > xLib( getOrCreateLibrary( _eType, _rLibName ), UNO_SET_THROW );
if ( xLib->hasByName( _rObjectName ) )
return false;
xLib->insertByName( _rObjectName, _rElement );
return true;
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
return false;
}
bool ScriptDocument::Impl::updateModule( const OUString& _rLibName, const OUString& _rModName, const OUString& _rModuleCode ) const
{
try
{
Reference< XNameContainer > xLib( getOrCreateLibrary( E_SCRIPTS, _rLibName ), UNO_SET_THROW );
if ( !xLib->hasByName( _rModName ) )
return false;
xLib->replaceByName( _rModName, Any( _rModuleCode ) );
return true;
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
return false;
}
bool ScriptDocument::Impl::createDialog( const OUString& _rLibName, const OUString& _rDialogName, Reference< XInputStreamProvider >& _out_rDialogProvider ) const
{
try
{
Reference< XNameContainer > xLib( getLibrary( E_DIALOGS, _rLibName, true ), UNO_SET_THROW );
// create dialog
_out_rDialogProvider.clear();
if ( xLib->hasByName( _rDialogName ) )
return false;
// create new dialog model
const Reference< XComponentContext >& aContext(
comphelper::getProcessComponentContext() );
Reference< XNameContainer > xDialogModel(
aContext->getServiceManager()->createInstanceWithContext(
u"com.sun.star.awt.UnoControlDialogModel"_ustr, aContext ),
UNO_QUERY_THROW );
// set name property
Reference< XPropertySet > xDlgPSet( xDialogModel, UNO_QUERY_THROW );
xDlgPSet->setPropertyValue( DLGED_PROP_NAME, Any( _rDialogName ) );
// export dialog model
_out_rDialogProvider = ::xmlscript::exportDialogModel( xDialogModel, aContext, isDocument() ? getDocument() : Reference< XModel >() );
// insert dialog into library
xLib->insertByName( _rDialogName, Any( _out_rDialogProvider ) );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
return _out_rDialogProvider.is();
}
void ScriptDocument::Impl::setDocumentModified() const
{
OSL_ENSURE( isValid() && isDocument(), "ScriptDocument::Impl::setDocumentModified: only to be called for real documents!" );
if ( isValid() && isDocument() )
{
try
{
m_xDocModify->setModified( true );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
}
}
bool ScriptDocument::Impl::isDocumentModified() const
{
OSL_ENSURE( isValid() && isDocument(), "ScriptDocument::Impl::isDocumentModified: only to be called for real documents!" );
bool bIsModified = false;
if ( isValid() && isDocument() )
{
try
{
bIsModified = m_xDocModify->isModified();
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
}
return bIsModified;
}
void ScriptDocument::Impl::saveDocument( const Reference< XStatusIndicator >& _rxStatusIndicator ) const
{
Reference< XFrame > xFrame;
if ( !getCurrentFrame( xFrame ) )
return;
Sequence< PropertyValue > aArgs;
if ( _rxStatusIndicator.is() )
{
aArgs = ::comphelper::InitPropertySequence({
{ "StatusIndicator", Any(_rxStatusIndicator) }
});
}
try
{
URL aURL;
aURL.Complete = ".uno:Save" ;
aURL.Main = aURL.Complete;
aURL.Protocol = ".uno:" ;
aURL.Path = "Save" ;
Reference< XDispatchProvider > xDispProv( xFrame, UNO_QUERY_THROW );
Reference< XDispatch > xDispatch(
xDispProv->queryDispatch( aURL, u"_self"_ustr, FrameSearchFlag::AUTO ),
UNO_SET_THROW );
xDispatch->dispatch( aURL, aArgs );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
}
OUString ScriptDocument::Impl::getTitle() const
{
OSL_PRECOND( isValid() && isDocument(), "ScriptDocument::Impl::getTitle: for documents only!" );
OUString sTitle;
if ( isValid() && isDocument() )
{
sTitle = ::comphelper::DocumentInfo::getDocumentTitle( m_xDocument );
}
return sTitle;
}
OUString ScriptDocument::Impl::getURL() const
{
OSL_PRECOND( isValid() && isDocument(), "ScriptDocument::Impl::getURL: for documents only!" );
OUString sURL;
if ( isValid() && isDocument() )
{
try
{
sURL = m_xDocument->getURL();
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
}
return sURL;
}
bool ScriptDocument::Impl::allowMacros() const
{
OSL_ENSURE( isValid() && isDocument(), "ScriptDocument::Impl::allowMacros: for documents only!" );
bool bAllow = false;
if ( isValid() && isDocument() )
{
try
{
bAllow = m_xScriptAccess->getAllowMacroExecution();
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
}
return bAllow;
}
bool ScriptDocument::Impl::getCurrentFrame( Reference< XFrame >& _out_rxFrame ) const
{
_out_rxFrame.clear();
OSL_PRECOND( isValid() && isDocument(), "ScriptDocument::Impl::getCurrentFrame: documents only!" );
if ( !isValid() || !isDocument() )
return false;
try
{
Reference< XModel > xDocument( m_xDocument, UNO_SET_THROW );
Reference< XController > xController( xDocument->getCurrentController(), UNO_SET_THROW );
_out_rxFrame.set( xController->getFrame(), UNO_SET_THROW );
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
return _out_rxFrame.is();
}
bool ScriptDocument::Impl::isLibraryShared( const OUString& _rLibName, LibraryContainerType _eType )
{
bool bIsShared = false;
try
{
Reference< XLibraryContainer2 > xLibContainer( getLibraryContainer( _eType ), UNO_QUERY_THROW );
if ( !xLibContainer->hasByName( _rLibName ) || !xLibContainer->isLibraryLink( _rLibName ) )
return false;
OUString aFileURL;
const Reference< XComponentContext >& xContext( ::comphelper::getProcessComponentContext() );
Reference< XUriReferenceFactory > xUriFac = UriReferenceFactory::create(xContext);
OUString aLinkURL( xLibContainer->getLibraryLinkURL( _rLibName ) );
Reference< XUriReference > xUriRef( xUriFac->parse( aLinkURL ), UNO_SET_THROW );
OUString aScheme = xUriRef->getScheme();
if ( aScheme.equalsIgnoreAsciiCase("file") )
{
aFileURL = aLinkURL;
}
else if ( aScheme.equalsIgnoreAsciiCase("vnd.sun.star.pkg") )
{
OUString aDecodedURL = xUriRef->getAuthority();
if (aDecodedURL.startsWithIgnoreAsciiCase("vnd.sun.star.expand:", &aDecodedURL))
{
aDecodedURL = ::rtl::Uri::decode( aDecodedURL, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
Reference< XMacroExpander > xMacroExpander = theMacroExpander::get(xContext);
aFileURL = xMacroExpander->expandMacros( aDecodedURL );
}
}
if ( !aFileURL.isEmpty() )
{
::osl::DirectoryItem aFileItem;
::osl::FileStatus aFileStatus( osl_FileStatus_Mask_FileURL );
OSL_VERIFY( ::osl::DirectoryItem::get( aFileURL, aFileItem ) == ::osl::FileBase::E_None );
OSL_VERIFY( aFileItem.getFileStatus( aFileStatus ) == ::osl::FileBase::E_None );
OUString aCanonicalFileURL( aFileStatus.getFileURL() );
if( aCanonicalFileURL.indexOf( LIBO_SHARE_FOLDER "/basic" ) >= 0 ||
aCanonicalFileURL.indexOf( LIBO_SHARE_FOLDER "/uno_packages" ) >= 0 ||
aCanonicalFileURL.indexOf( LIBO_SHARE_FOLDER "/extensions" ) >= 0 )
bIsShared = true;
}
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
return bIsShared;
}
void ScriptDocument::Impl::onDocumentCreated( const ScriptDocument& /*_rDocument*/ )
{
// not interested in
}
void ScriptDocument::Impl::onDocumentOpened( const ScriptDocument& /*_rDocument*/ )
{
// not interested in
}
void ScriptDocument::Impl::onDocumentSave( const ScriptDocument& /*_rDocument*/ )
{
// not interested in
}
void ScriptDocument::Impl::onDocumentSaveDone( const ScriptDocument& /*_rDocument*/ )
{
// not interested in
}
void ScriptDocument::Impl::onDocumentSaveAs( const ScriptDocument& /*_rDocument*/ )
{
// not interested in
}
void ScriptDocument::Impl::onDocumentSaveAsDone( const ScriptDocument& /*_rDocument*/ )
{
// not interested in
}
void ScriptDocument::Impl::onDocumentClosed( const ScriptDocument& _rDocument )
{
DBG_TESTSOLARMUTEX();
OSL_PRECOND( isValid(), "ScriptDocument::Impl::onDocumentClosed: should not be listening if I'm not valid!" );
bool bMyDocument = m_xDocument == _rDocument.getDocument();
OSL_PRECOND( bMyDocument, "ScriptDocument::Impl::onDocumentClosed: didn't want to know *this*!" );
if ( bMyDocument )
{
m_bDocumentClosed = true;
}
}
void ScriptDocument::Impl::onDocumentTitleChanged( const ScriptDocument& /*_rDocument*/ )
{
// not interested in
}
void ScriptDocument::Impl::onDocumentModeChanged( const ScriptDocument& /*_rDocument*/ )
{
// not interested in
}
ScriptDocument::ScriptDocument()
:m_pImpl(std::make_shared<Impl>())
{ }
ScriptDocument::ScriptDocument( ScriptDocument::SpecialDocument _eType )
:m_pImpl( std::make_shared<Impl>( Reference< XModel >() ) )
{
OSL_ENSURE( _eType == NoDocument, "ScriptDocument::ScriptDocument: unknown SpecialDocument type!" );
}
ScriptDocument::ScriptDocument( const Reference< XModel >& _rxDocument )
:m_pImpl( std::make_shared<Impl>( _rxDocument ) )
{
OSL_ENSURE( _rxDocument.is(), "ScriptDocument::ScriptDocument: document must not be NULL!" );
// a NULL document results in an uninitialized instance, and for this
// purpose, there is a dedicated constructor
}
const ScriptDocument& ScriptDocument::getApplicationScriptDocument()
{
static ScriptDocument s_aApplicationScripts;
return s_aApplicationScripts;
}
ScriptDocument ScriptDocument::getDocumentForBasicManager( const BasicManager* _pManager )
{
if ( _pManager == SfxApplication::GetBasicManager() )
return getApplicationScriptDocument();
docs::Documents aDocuments;
lcl_getAllModels_throw( aDocuments, false );
for (auto const& doc : aDocuments)
{
const BasicManager* pDocBasicManager = ::basic::BasicManagerRepository::getDocumentBasicManager( doc.xModel );
if ( ( pDocBasicManager != SfxApplication::GetBasicManager() )
&& ( pDocBasicManager == _pManager )
)
{
return ScriptDocument( doc.xModel );
}
}
OSL_FAIL( "ScriptDocument::getDocumentForBasicManager: did not find a document for this manager!" );
return ScriptDocument( NoDocument );
}
ScriptDocument ScriptDocument::getDocumentWithURLOrCaption( std::u16string_view _rUrlOrCaption )
{
ScriptDocument aDocument( getApplicationScriptDocument() );
if ( _rUrlOrCaption.empty() )
return aDocument;
docs::Documents aDocuments;
lcl_getAllModels_throw( aDocuments, false );
for (auto const& doc : aDocuments)
{
const ScriptDocument aCheck( doc.xModel );
if ( _rUrlOrCaption == aCheck.getTitle()
|| _rUrlOrCaption == aCheck.m_pImpl->getURL()
)
{
aDocument = aCheck;
break;
}
}
return aDocument;
}
ScriptDocuments ScriptDocument::getAllScriptDocuments( ScriptDocument::ScriptDocumentList _eListType )
{
ScriptDocuments aScriptDocs;
// include application?
if ( _eListType == AllWithApplication )
aScriptDocs.push_back( getApplicationScriptDocument() );
// obtain documents
try
{
docs::Documents aDocuments;
lcl_getAllModels_throw( aDocuments, true /* exclude invisible */ );
for (auto const& doc : aDocuments)
{
// exclude documents without script/library containers
ScriptDocument aDoc( doc.xModel );
if ( !aDoc.isValid() )
continue;
aScriptDocs.push_back( aDoc );
}
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
// sort document list by doc title?
if ( _eListType == DocumentsSorted )
{
auto const sort = comphelper::string::NaturalStringSorter(
comphelper::getProcessComponentContext(),
Application::GetSettings().GetUILanguageTag().getLocale());
std::sort(aScriptDocs.begin(), aScriptDocs.end(),
[&sort](const ScriptDocument& rLHS, const ScriptDocument& rRHS) {
return sort.compare(rLHS.getTitle(), rRHS.getTitle()) < 0;
});
}
return aScriptDocs;
}
bool ScriptDocument::operator==( const ScriptDocument& _rhs ) const
{
return m_pImpl->getDocumentRef() == _rhs.m_pImpl->getDocumentRef();
}
sal_Int32 ScriptDocument::hashCode() const
{
return sal::static_int_cast<sal_Int32>(reinterpret_cast< sal_IntPtr >( m_pImpl->getDocumentRef().get() ));
}
bool ScriptDocument::isValid() const
{
return m_pImpl->isValid();
}
bool ScriptDocument::isAlive() const
{
return m_pImpl->isAlive();
}
Reference< XLibraryContainer > ScriptDocument::getLibraryContainer( LibraryContainerType _eType ) const
{
return m_pImpl->getLibraryContainer( _eType );
}
Reference< XNameContainer > ScriptDocument::getLibrary( LibraryContainerType _eType, const OUString& _rLibName, bool _bLoadLibrary ) const
{
return m_pImpl->getLibrary( _eType, _rLibName, _bLoadLibrary );
}
bool ScriptDocument::hasLibrary( LibraryContainerType _eType, const OUString& _rLibName ) const
{
return m_pImpl->hasLibrary( _eType, _rLibName );
}
Reference< XNameContainer > ScriptDocument::getOrCreateLibrary( LibraryContainerType _eType, const OUString& _rLibName ) const
{
return m_pImpl->getOrCreateLibrary( _eType, _rLibName );
}
void ScriptDocument::loadLibraryIfExists( LibraryContainerType _eType, const OUString& _rLibrary )
{
m_pImpl->loadLibraryIfExists( _eType, _rLibrary );
}
Sequence< OUString > ScriptDocument::getObjectNames( LibraryContainerType _eType, const OUString& _rLibName ) const
{
Sequence< OUString > aModuleNames;
try
{
if ( hasLibrary( _eType, _rLibName ) )
{
Reference< XNameContainer > xLib( getLibrary( _eType, _rLibName, false ) );
if ( xLib.is() )
aModuleNames = xLib->getElementNames();
}
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
// sort
auto const sort = comphelper::string::NaturalStringSorter(
comphelper::getProcessComponentContext(),
Application::GetSettings().GetUILanguageTag().getLocale());
auto [begin, end] = asNonConstRange(aModuleNames);
std::sort(begin, end,
[&sort](const OUString& rLHS, const OUString& rRHS) {
return sort.compare(rLHS, rRHS) < 0;
});
return aModuleNames;
}
OUString ScriptDocument::createObjectName( LibraryContainerType _eType, const OUString& _rLibName ) const
{
OUString aObjectName;
OUString aBaseName = _eType == E_SCRIPTS ? u"Module"_ustr : u"Dialog"_ustr;
const Sequence< OUString > aUsedNames( getObjectNames( _eType, _rLibName ) );
std::set< OUString > aUsedNamesCheck( aUsedNames.begin(), aUsedNames.end() );
bool bValid = false;
sal_Int32 i = 1;
while ( !bValid )
{
aObjectName = aBaseName
+ OUString::number( i );
if ( aUsedNamesCheck.find( aObjectName ) == aUsedNamesCheck.end() )
bValid = true;
++i;
}
return aObjectName;
}
Sequence< OUString > ScriptDocument::getLibraryNames() const
{
return GetMergedLibraryNames( getLibraryContainer( E_SCRIPTS ), getLibraryContainer( E_DIALOGS ) );
}
bool ScriptDocument::isReadOnly() const
{
return m_pImpl->isReadOnly();
}
bool ScriptDocument::isApplication() const
{
return m_pImpl->isApplication();
}
bool ScriptDocument::isInVBAMode() const
{
return m_pImpl->isInVBAMode();
}
BasicManager* ScriptDocument::getBasicManager() const
{
return m_pImpl->getBasicManager();
}
Reference< XModel > ScriptDocument::getDocument() const
{
return m_pImpl->getDocument();
}
Reference< XModel > ScriptDocument::getDocumentOrNull() const
{
if ( isDocument() )
return m_pImpl->getDocument();
return nullptr;
}
bool ScriptDocument::removeModule( const OUString& _rLibName, const OUString& _rModuleName ) const
{
return m_pImpl->removeModuleOrDialog( E_SCRIPTS, _rLibName, _rModuleName );
}
bool ScriptDocument::hasModule( const OUString& _rLibName, const OUString& _rModuleName ) const
{
return m_pImpl->hasModuleOrDialog( E_SCRIPTS, _rLibName, _rModuleName );
}
bool ScriptDocument::getModule( const OUString& _rLibName, const OUString& _rModName, OUString& _out_rModuleSource ) const
{
Any aCode;
if ( !m_pImpl->getModuleOrDialog( E_SCRIPTS, _rLibName, _rModName, aCode ) )
return false;
OSL_VERIFY( aCode >>= _out_rModuleSource );
return true;
}
bool ScriptDocument::renameModule( const OUString& _rLibName, const OUString& _rOldName, const OUString& _rNewName ) const
{
return m_pImpl->renameModuleOrDialog( E_SCRIPTS, _rLibName, _rOldName, _rNewName, nullptr );
}
bool ScriptDocument::createModule( const OUString& _rLibName, const OUString& _rModName, bool _bCreateMain, OUString& _out_rNewModuleCode ) const
{
if ( !m_pImpl->createModule( _rLibName, _rModName, _bCreateMain, _out_rNewModuleCode ) )
return false;
// doc shell modified
MarkDocumentModified( *const_cast< ScriptDocument* >( this ) ); // here?
return true;
}
bool ScriptDocument::insertModule( const OUString& _rLibName, const OUString& _rModName, const OUString& _rModuleCode ) const
{
return m_pImpl->insertModuleOrDialog( E_SCRIPTS, _rLibName, _rModName, Any( _rModuleCode ) );
}
bool ScriptDocument::updateModule( const OUString& _rLibName, const OUString& _rModName, const OUString& _rModuleCode ) const
{
return m_pImpl->updateModule( _rLibName, _rModName, _rModuleCode );
}
bool ScriptDocument::removeDialog( const OUString& _rLibName, const OUString& _rDialogName ) const
{
return m_pImpl->removeModuleOrDialog( E_DIALOGS, _rLibName, _rDialogName );
}
bool ScriptDocument::hasDialog( const OUString& _rLibName, const OUString& _rDialogName ) const
{
return m_pImpl->hasModuleOrDialog( E_DIALOGS, _rLibName, _rDialogName );
}
bool ScriptDocument::getDialog( const OUString& _rLibName, const OUString& _rDialogName, Reference< XInputStreamProvider >& _out_rDialogProvider ) const
{
Any aCode;
if ( !m_pImpl->getModuleOrDialog( E_DIALOGS, _rLibName, _rDialogName, aCode ) )
return false;
OSL_VERIFY( aCode >>= _out_rDialogProvider );
return _out_rDialogProvider.is();
}
bool ScriptDocument::renameDialog( const OUString& _rLibName, const OUString& _rOldName, const OUString& _rNewName, const Reference< XNameContainer >& _rxExistingDialogModel ) const
{
return m_pImpl->renameModuleOrDialog( E_DIALOGS, _rLibName, _rOldName, _rNewName, _rxExistingDialogModel );
}
bool ScriptDocument::createDialog( const OUString& _rLibName, const OUString& _rDialogName, Reference< XInputStreamProvider >& _out_rDialogProvider ) const
{
if ( !m_pImpl->createDialog( _rLibName, _rDialogName, _out_rDialogProvider ) )
return false;
MarkDocumentModified( *const_cast< ScriptDocument* >( this ) ); // here?
return true;
}
bool ScriptDocument::insertDialog( const OUString& _rLibName, const OUString& _rDialogName, const Reference< XInputStreamProvider >& _rxDialogProvider ) const
{
return m_pImpl->insertModuleOrDialog( E_DIALOGS, _rLibName, _rDialogName, Any( _rxDialogProvider ) );
}
void ScriptDocument::setDocumentModified() const
{
m_pImpl->setDocumentModified();
}
bool ScriptDocument::isDocumentModified() const
{
return m_pImpl->isDocumentModified();
}
void ScriptDocument::saveDocument( const Reference< XStatusIndicator >& _rxStatusIndicator ) const
{
m_pImpl->saveDocument( _rxStatusIndicator );
}
LibraryLocation ScriptDocument::getLibraryLocation( const OUString& _rLibName ) const
{
LibraryLocation eLocation = LIBRARY_LOCATION_UNKNOWN;
if ( !_rLibName.isEmpty() )
{
if ( isDocument() )
{
eLocation = LIBRARY_LOCATION_DOCUMENT;
}
else
{
if ( ( hasLibrary( E_SCRIPTS, _rLibName ) && !m_pImpl->isLibraryShared( _rLibName, E_SCRIPTS ) )
|| ( hasLibrary( E_DIALOGS, _rLibName ) && !m_pImpl->isLibraryShared( _rLibName, E_DIALOGS ) )
)
{
eLocation = LIBRARY_LOCATION_USER;
}
else
{
eLocation = LIBRARY_LOCATION_SHARE;
}
}
}
return eLocation;
}
OUString ScriptDocument::getTitle( LibraryLocation _eLocation, LibraryType _eType ) const
{
OUString aTitle;
switch ( _eLocation )
{
case LIBRARY_LOCATION_USER:
{
switch ( _eType )
{
case LibraryType::Module: aTitle = IDEResId(RID_STR_USERMACROS); break;
case LibraryType::Dialog: aTitle = IDEResId(RID_STR_USERDIALOGS); break;
case LibraryType::All: aTitle = IDEResId(RID_STR_USERMACROSDIALOGS); break;
default:
break;
}
}
break;
case LIBRARY_LOCATION_SHARE:
{
switch ( _eType )
{
case LibraryType::Module: aTitle = IDEResId(RID_STR_SHAREMACROS); break;
case LibraryType::Dialog: aTitle = IDEResId(RID_STR_SHAREDIALOGS); break;
case LibraryType::All: aTitle = IDEResId(RID_STR_SHAREMACROSDIALOGS); break;
default:
break;
}
}
break;
case LIBRARY_LOCATION_DOCUMENT:
aTitle = getTitle();
break;
default:
break;
}
return aTitle;
}
OUString ScriptDocument::getTitle() const
{
return m_pImpl->getTitle();
}
bool ScriptDocument::isActive() const
{
bool bIsActive( false );
try
{
Reference< XFrame > xFrame;
if ( m_pImpl->getCurrentFrame( xFrame ) )
bIsActive = xFrame->isActive();
}
catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("basctl.basicide");
}
return bIsActive;
}
bool ScriptDocument::allowMacros() const
{
return m_pImpl->allowMacros();
}
} // namespace basctl
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */