summaryrefslogtreecommitdiffstats
path: root/vbahelper/source/vbahelper/vbahelper.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vbahelper/source/vbahelper/vbahelper.cxx')
-rw-r--r--vbahelper/source/vbahelper/vbahelper.cxx1113
1 files changed, 1113 insertions, 0 deletions
diff --git a/vbahelper/source/vbahelper/vbahelper.cxx b/vbahelper/source/vbahelper/vbahelper.cxx
new file mode 100644
index 000000000..b0f6b291e
--- /dev/null
+++ b/vbahelper/source/vbahelper/vbahelper.cxx
@@ -0,0 +1,1113 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column:100 -*- */
+/*
+ * 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 <com/sun/star/util/URLTransformer.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/frame/XModel2.hpp>
+#include <com/sun/star/script/BasicErrorException.hpp>
+#include <com/sun/star/script/XDefaultProperty.hpp>
+#include <com/sun/star/script/XInvocation.hpp>
+#include <com/sun/star/script/Converter.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/theIntrospection.hpp>
+#include <com/sun/star/util/MeasureUnit.hpp>
+#include <com/sun/star/awt/XControl.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/awt/XDialog.hpp>
+#include <com/sun/star/awt/XUnitConversion.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <ooo/vba/XHelperInterface.hpp>
+
+#include <comphelper/automationinvokedzone.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/servicehelper.hxx>
+
+#include <sfx2/objsh.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/dispatch.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <svl/stritem.hxx>
+#include <svl/eitem.hxx>
+#include <svl/intitem.hxx>
+#include <svl/itemset.hxx>
+#include <sfx2/docfac.hxx>
+#include <sfx2/viewfac.hxx>
+
+#include <basic/sbstar.hxx>
+#include <basic/basmgr.hxx>
+#include <basic/sbmod.hxx>
+#include <basic/sbuno.hxx>
+#include <basic/sberrors.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sfx2/viewsh.hxx>
+#include <sal/log.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <vcl/syswin.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/UnitConversion.hxx>
+#include <vbahelper/vbahelper.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::ooo::vba;
+
+
+namespace ooo::vba
+{
+
+// helper method to determine if the view ( calc ) is in print-preview mode
+static bool isInPrintPreview( SfxViewFrame* pView )
+{
+ sal_uInt16 nViewNo = SID_VIEWSHELL1 - SID_VIEWSHELL0;
+ if ( pView->GetObjectShell()->GetFactory().GetViewFactoryCount() >
+nViewNo && !pView->GetObjectShell()->IsInPlaceActive() )
+ {
+ SfxViewFactory &rViewFactory =
+ pView->GetObjectShell()->GetFactory().GetViewFactory(nViewNo);
+ if ( pView->GetCurViewId() == rViewFactory.GetOrdinal() )
+ return true;
+ }
+ return false;
+}
+
+uno::Reference< beans::XIntrospectionAccess >
+getIntrospectionAccess( const uno::Any& aObject )
+{
+ static uno::Reference< beans::XIntrospection > xIntrospection( beans::theIntrospection::get( comphelper::getProcessComponentContext() ) );
+ return xIntrospection->inspect( aObject );
+}
+
+uno::Reference< script::XTypeConverter > const &
+getTypeConverter( const uno::Reference< uno::XComponentContext >& xContext )
+{
+ static uno::Reference< script::XTypeConverter > xTypeConv( script::Converter::create(xContext) );
+ return xTypeConv;
+}
+const uno::Any&
+aNULL()
+{
+ static uno::Any aNULLL{ uno::Reference< uno::XInterface >() };
+ return aNULLL;
+}
+
+void dispatchExecute(SfxViewShell const * pViewShell, sal_uInt16 nSlot)
+{
+ SfxViewFrame* pViewFrame = nullptr;
+ if ( pViewShell )
+ pViewFrame = pViewShell->GetViewFrame();
+ if ( pViewFrame )
+ {
+ SfxDispatcher* pDispatcher = pViewFrame->GetDispatcher();
+ if( pDispatcher )
+ {
+ pDispatcher->Execute( nSlot , SfxCallMode::SYNCHRON );
+ }
+ }
+}
+
+void
+dispatchRequests (const uno::Reference< frame::XModel>& xModel, const OUString & aUrl, const uno::Sequence< beans::PropertyValue >& sProps )
+{
+ util::URL url;
+ url.Complete = aUrl;
+ uno::Reference<frame::XController> xController = xModel->getCurrentController();
+ uno::Reference<frame::XFrame> xFrame = xController->getFrame();
+ uno::Reference<frame::XDispatchProvider> xDispatchProvider (xFrame,uno::UNO_QUERY_THROW);
+ try
+ {
+ uno::Reference<uno::XComponentContext > xContext(
+ comphelper::getProcessComponentContext() );
+ uno::Reference<util::XURLTransformer> xParser( util::URLTransformer::create(xContext) );
+ xParser->parseStrict (url);
+ }
+ catch (const uno::Exception&)
+ {
+ return;
+ }
+
+ uno::Reference<frame::XDispatch> xDispatcher = xDispatchProvider->queryDispatch(url,"",0);
+
+ sal_Int32 nProps = sProps.getLength();
+ uno::Sequence<beans::PropertyValue> dispatchProps(nProps + 1);
+
+ if ( nProps )
+ {
+ std::copy(sProps.begin(), sProps.end(), dispatchProps.getArray());
+ }
+
+ if ( xDispatcher.is() )
+ {
+ xDispatcher->dispatch( url, dispatchProps );
+ }
+}
+
+void
+dispatchRequests( const uno::Reference< frame::XModel>& xModel, const OUString& aUrl )
+{
+ uno::Sequence<beans::PropertyValue> dispatchProps;
+ dispatchRequests( xModel, aUrl, dispatchProps );
+}
+
+uno::Reference< frame::XModel >
+getCurrentDoc( const OUString& sKey )
+{
+ uno::Reference< frame::XModel > xModel;
+ StarBASIC* pBasic = SfxApplication::GetBasic();
+ if (pBasic == nullptr)
+ {
+ SAL_INFO("vbahelper", "getModelFromBasic() StarBASIC* is NULL" );
+ return xModel;
+ }
+ SbxObject* basicChosen = pBasic;
+ SbxObject* pParent = pBasic->GetParent();
+ SbxObject* pParentParent = pParent ? pParent->GetParent() : nullptr;
+
+ if( pParentParent )
+ {
+ basicChosen = pParentParent;
+ }
+ else if( pParent )
+ {
+ basicChosen = pParent;
+ }
+
+
+ uno::Any aModel;
+ SbxVariable *pCompVar = basicChosen->Find( sKey, SbxClassType::Object );
+
+ if ( pCompVar )
+ {
+ aModel = sbxToUnoValue( pCompVar );
+ if ( !( aModel >>= xModel ) || !xModel.is() )
+ {
+ throw uno::RuntimeException(
+ "Can't extract model from basic ( it's obviously not set yet therefore don't know the current document context)" );
+ }
+ SAL_INFO("vbahelper", "Have model points to url " << xModel->getURL());
+ }
+ else
+ {
+ SAL_INFO("vbahelper", "Failed to get " << sKey);
+ throw uno::RuntimeException( "Can't determine the currently selected document" );
+ }
+ return xModel;
+}
+
+/// @throws uno::RuntimeException
+static uno::Reference< frame::XModel >
+getCurrentDocCtx( const OUString& ctxName, const uno::Reference< uno::XComponentContext >& xContext )
+{
+ uno::Reference< frame::XModel > xModel;
+ // try fallback to calling doc
+ css::uno::Reference< css::container::XNameAccess > xNameAccess( xContext, css::uno::UNO_QUERY_THROW );
+ xModel.set( xNameAccess->getByName( ctxName ), uno::UNO_QUERY_THROW );
+ return xModel;
+}
+
+uno::Reference< frame::XModel >
+getThisExcelDoc( const uno::Reference< uno::XComponentContext >& xContext )
+{
+ return getCurrentDocCtx( "ExcelDocumentContext" , xContext );
+}
+
+uno::Reference< frame::XModel >
+getThisWordDoc( const uno::Reference< uno::XComponentContext >& xContext )
+{
+ return getCurrentDocCtx( "WordDocumentContext" , xContext );
+}
+
+ uno::Reference< frame::XModel >
+getCurrentExcelDoc( const uno::Reference< uno::XComponentContext >& xContext )
+{
+ uno::Reference< frame::XModel > xModel;
+ try
+ {
+ xModel = getCurrentDoc( "ThisExcelDoc" );
+ }
+ catch (const uno::Exception&)
+ {
+ try
+ {
+ xModel = getThisExcelDoc( xContext );
+ }
+ catch (const uno::Exception&)
+ {
+ }
+ }
+ return xModel;
+}
+
+ uno::Reference< frame::XModel >
+getCurrentWordDoc( const uno::Reference< uno::XComponentContext >& xContext )
+{
+ uno::Reference< frame::XModel > xModel;
+ try
+ {
+ xModel = getCurrentDoc( "ThisWordDoc" );
+ }
+ catch (const uno::Exception&)
+ {
+ try
+ {
+ xModel = getThisWordDoc( xContext );
+ }
+ catch (const uno::Exception&)
+ {
+ }
+ }
+ return xModel;
+}
+
+sal_Int32
+OORGBToXLRGB( sal_Int32 nCol )
+{
+ sal_Int32 nAutoBits = nCol;
+ nAutoBits &= 0xFF000000;
+ sal_Int32 nRed = nCol;
+ nRed &= 0x00FF0000;
+ nRed >>= 16;
+ sal_Int32 nGreen = nCol;
+ nGreen &= 0x0000FF00;
+ nGreen >>= 8;
+ sal_Int32 nBlue = nCol;
+ nBlue &= 0x000000FF;
+ sal_Int32 nRGB = ( nAutoBits | (nBlue << 16) | (nGreen << 8) | nRed );
+ return nRGB;
+}
+
+sal_Int32
+XLRGBToOORGB( sal_Int32 nCol )
+{
+ sal_Int32 nAutoBits = nCol;
+ nAutoBits &= 0xFF000000;
+
+ sal_Int32 nBlue = nCol;
+ nBlue &= 0x00FF0000;
+ nBlue >>= 16;
+ sal_Int32 nGreen = nCol;
+ nGreen &= 0x0000FF00;
+ nGreen >>= 8;
+ sal_Int32 nRed = nCol;
+ nRed &= 0x000000FF;
+ sal_Int32 nRGB = ( nAutoBits | (nRed << 16) | (nGreen << 8) | nBlue );
+ return nRGB;
+}
+uno::Any
+OORGBToXLRGB( const uno::Any& aCol )
+{
+ sal_Int32 nCol(0);
+ aCol >>= nCol;
+ nCol = OORGBToXLRGB( nCol );
+ return uno::Any( nCol );
+}
+uno::Any
+XLRGBToOORGB( const uno::Any& aCol )
+{
+ sal_Int32 nCol(0);
+ aCol >>= nCol;
+ nCol = XLRGBToOORGB( nCol );
+ return uno::Any( nCol );
+}
+
+void PrintOutHelper( SfxViewShell const * pViewShell, const uno::Any& From, const uno::Any& To, const uno::Any& Copies, const uno::Any& Preview, const uno::Any& /*ActivePrinter*/, const uno::Any& /*PrintToFile*/, const uno::Any& Collate, const uno::Any& PrToFileName, bool bUseSelection )
+{
+ sal_Int32 nTo = 0;
+ sal_Int32 nFrom = 0;
+ sal_Int16 nCopies = 1;
+ bool bPreview = false;
+ bool bCollate = false;
+ bool bSelection = bUseSelection;
+ From >>= nFrom;
+ To >>= nTo;
+ Copies >>= nCopies;
+ Preview >>= bPreview;
+ if ( nCopies > 1 ) // Collate only useful when more that 1 copy
+ Collate >>= bCollate;
+
+ OUString sRange( "-" );
+ OUString sFileName;
+
+ if ( nFrom || nTo )
+ {
+ if ( nFrom )
+ sRange = OUString::number( nFrom ) + sRange;
+ if ( nTo )
+ sRange += OUString::number( nTo );
+ }
+
+ PrToFileName >>= sFileName;
+ SfxViewFrame* pViewFrame = nullptr;
+ if ( pViewShell )
+ pViewFrame = pViewShell->GetViewFrame();
+ if ( !pViewFrame )
+ return;
+
+ SfxAllItemSet aArgs( SfxGetpApp()->GetPool() );
+
+ SfxBoolItem sfxCollate( SID_PRINT_COLLATE, bCollate );
+ aArgs.Put( sfxCollate, sfxCollate.Which() );
+ SfxInt16Item sfxCopies( SID_PRINT_COPIES, nCopies );
+ aArgs.Put( sfxCopies, sfxCopies.Which() );
+ if ( !sFileName.isEmpty() )
+ {
+ SfxStringItem sfxFileName( SID_FILE_NAME, sFileName);
+ aArgs.Put( sfxFileName, sfxFileName.Which() );
+
+ }
+ if ( !sRange.isEmpty() )
+ {
+ SfxStringItem sfxRange( SID_PRINT_PAGES, sRange );
+ aArgs.Put( sfxRange, sfxRange.Which() );
+ }
+ SfxBoolItem sfxSelection( SID_SELECTION, bSelection );
+ aArgs.Put( sfxSelection, sfxSelection.Which() );
+ SfxBoolItem sfxAsync( SID_ASYNCHRON, false );
+ aArgs.Put( sfxAsync, sfxAsync.Which() );
+ SfxDispatcher* pDispatcher = pViewFrame->GetDispatcher();
+
+ if ( !pDispatcher )
+ return;
+
+ if ( bPreview )
+ {
+ if ( !pViewFrame->GetFrame().IsInPlace() )
+ {
+ // #TODO is this necessary ( calc specific )
+// SC_MOD()->InputEnterHandler();
+ pViewFrame->GetDispatcher()->Execute( SID_VIEWSHELL1, SfxCallMode::SYNCHRON );
+ WaitUntilPreviewIsClosed( pViewFrame );
+ }
+ }
+ else
+ pDispatcher->Execute( sal_uInt16(SID_PRINTDOC), SfxCallMode::SYNCHRON, aArgs );
+
+
+ // #FIXME #TODO
+ // 1 ActivePrinter ( how/can we switch a printer via API? )
+ // 2 PrintToFile ( ms behaviour if this option is specified but no
+ // filename supplied 'PrToFileName' then the user will be prompted )
+ // 3 Need to check behaviour of Selected sheets with range ( e.g. From & To
+ // values ) in oOO these options are mutually exclusive
+ // 4 There is a pop up to do with transparent objects in the print source
+ // should be able to disable that via configuration for the duration
+ // of this method
+}
+
+void PrintPreviewHelper( const css::uno::Any& /*EnableChanges*/, SfxViewShell const * pViewShell )
+{
+ SfxViewFrame* pViewFrame = nullptr;
+ if ( pViewShell )
+ pViewFrame = pViewShell->GetViewFrame();
+ if ( pViewFrame )
+ {
+ if ( !pViewFrame->GetFrame().IsInPlace() )
+ {
+ dispatchExecute( pViewShell, SID_VIEWSHELL1 );
+ WaitUntilPreviewIsClosed( pViewFrame );
+ }
+ }
+}
+
+void WaitUntilPreviewIsClosed( SfxViewFrame* pViewFrame )
+{
+ while ( pViewFrame && isInPrintPreview( pViewFrame ) && !Application::IsQuit())
+ Application::Yield();
+}
+
+bool extractBoolFromAny( const uno::Any& rAny )
+{
+ switch( rAny.getValueType().getTypeClass() )
+ {
+ case uno::TypeClass_BOOLEAN:
+ return rAny.get< bool >();
+ case uno::TypeClass_FLOAT:
+ return rAny.get< float >() != 0.0;
+ case uno::TypeClass_DOUBLE:
+ return rAny.get< double >() != 0.0;
+ case uno::TypeClass_BYTE:
+ case uno::TypeClass_SHORT:
+ case uno::TypeClass_LONG:
+ return rAny.get< sal_Int32 >() != 0;
+ case uno::TypeClass_HYPER:
+ return rAny.get< sal_Int64 >() != 0;
+ default:;
+ }
+ throw uno::RuntimeException( "Invalid type, cannot convert to boolean." , nullptr );
+}
+
+OUString extractStringFromAny( const uno::Any& rAny, bool bUppercaseBool )
+{
+ switch( rAny.getValueType().getTypeClass() )
+ {
+ case uno::TypeClass_STRING:
+ return rAny.get< OUString >();
+ case uno::TypeClass_BOOLEAN:
+ return bUppercaseBool ?
+ (rAny.get< bool >() ? OUString( "TRUE" ) : OUString( "FALSE" )) :
+ OUString::boolean( rAny.get< bool >() );
+ case uno::TypeClass_FLOAT:
+ return OUString::number( rAny.get< float >() );
+ case uno::TypeClass_DOUBLE:
+ return OUString::number( rAny.get< double >() );
+ case uno::TypeClass_BYTE:
+ case uno::TypeClass_SHORT:
+ case uno::TypeClass_LONG:
+ return OUString::number( rAny.get< sal_Int32 >() );
+ case uno::TypeClass_HYPER:
+ return OUString::number( rAny.get< sal_Int64 >() );
+ default:;
+ }
+ throw uno::RuntimeException( "Invalid type, cannot convert to string." , nullptr );
+}
+
+OUString extractStringFromAny( const uno::Any& rAny, const OUString& rDefault, bool bUppercaseBool )
+{
+ return rAny.hasValue() ? extractStringFromAny( rAny, bUppercaseBool ) : rDefault;
+}
+
+OUString getAnyAsString( const uno::Any& pvargItem )
+{
+ return extractStringFromAny( pvargItem );
+}
+
+
+OUString
+ContainerUtilities::getUniqueName( const uno::Sequence< OUString >& _slist, const OUString& _sElementName, std::u16string_view _sSuffixSeparator)
+{
+ return getUniqueName(_slist, _sElementName, _sSuffixSeparator, sal_Int32(2));
+}
+
+OUString
+ContainerUtilities::getUniqueName( const uno::Sequence< OUString >& _slist, const OUString& _sElementName, std::u16string_view _sSuffixSeparator, sal_Int32 _nStartSuffix)
+{
+ if ( !_slist.hasElements() )
+ return _sElementName;
+
+ OUString scompname = _sElementName;
+ sal_Int32 a = _nStartSuffix;
+
+ for (;;)
+ {
+ if (FieldInList(_slist, scompname) == -1)
+ return scompname;
+
+ scompname = _sElementName + _sSuffixSeparator + OUString::number( a++ );
+ }
+}
+
+sal_Int32
+ContainerUtilities::FieldInList( const uno::Sequence< OUString >& SearchList, const OUString& SearchString )
+{
+ // I wonder why comparing lexicographically is done
+ // when it's a match, is it interesting?
+ return comphelper::findValue(SearchList, SearchString);
+}
+
+static bool NeedEsc(sal_Unicode cCode)
+{
+ return OUString(".^$+\\|{}()").indexOf(cCode) != -1;
+}
+
+OUString VBAToRegexp(const OUString &rIn)
+{
+ OUStringBuffer sResult;
+ const sal_Unicode *start = rIn.getStr();
+ const sal_Unicode *end = start + rIn.getLength();
+
+ int seenright = 0;
+
+ while (start < end)
+ {
+ switch (*start)
+ {
+ case '?':
+ sResult.append('.');
+ start++;
+ break;
+ case '*':
+ sResult.append(".*");
+ start++;
+ break;
+ case '#':
+ sResult.append("[0-9]");
+ start++;
+ break;
+ case '~':
+ sResult.append('\\');
+ sResult.append(*(++start));
+ start++;
+ break;
+ // dump the ~ and escape the next character
+ case ']':
+ sResult.append('\\');
+ sResult.append(*start++);
+ break;
+ case '[':
+ sResult.append(*start++);
+ seenright = 0;
+ while (start < end && !seenright)
+ {
+ switch (*start)
+ {
+ case '[':
+ case '?':
+ case '*':
+ sResult.append('\\');
+ sResult.append(*start);
+ break;
+ case ']':
+ sResult.append(*start);
+ seenright = 1;
+ break;
+ case '!':
+ sResult.append('^');
+ break;
+ default:
+ if (NeedEsc(*start))
+ sResult.append('\\');
+ sResult.append(*start);
+ break;
+ }
+ start++;
+ }
+ break;
+ default:
+ if (NeedEsc(*start))
+ sResult.append('\\');
+ sResult.append(*start++);
+ }
+ }
+
+ return sResult.makeStringAndClear( );
+}
+
+double getPixelTo100thMillimeterConversionFactor( const css::uno::Reference< css::awt::XDevice >& xDevice, bool bVertical)
+{
+ double fConvertFactor = 1.0;
+ if( bVertical )
+ {
+ fConvertFactor = xDevice->getInfo().PixelPerMeterY/100000;
+ }
+ else
+ {
+ fConvertFactor = xDevice->getInfo().PixelPerMeterX/100000;
+ }
+ return fConvertFactor;
+}
+
+double PointsToPixels( const css::uno::Reference< css::awt::XDevice >& xDevice, double fPoints, bool bVertical)
+{
+ double fConvertFactor = getPixelTo100thMillimeterConversionFactor( xDevice, bVertical );
+ return convertPointToMm100(fPoints) * fConvertFactor;
+}
+double PixelsToPoints( const css::uno::Reference< css::awt::XDevice >& xDevice, double fPixels, bool bVertical)
+{
+ double fConvertFactor = getPixelTo100thMillimeterConversionFactor( xDevice, bVertical );
+ return convertMm100ToPoint(fPixels / fConvertFactor);
+}
+
+sal_Int32 PointsToHmm(double fPoints) { return std::round(convertPointToMm100(fPoints)); }
+
+double HmmToPoints(sal_Int32 nHmm) { return convertMm100ToPoint<double>(nHmm); }
+
+ConcreteXShapeGeometryAttributes::ConcreteXShapeGeometryAttributes( const css::uno::Reference< css::drawing::XShape >& xShape )
+{
+ m_pShapeHelper.reset( new ShapeHelper( xShape ) );
+}
+ConcreteXShapeGeometryAttributes::~ConcreteXShapeGeometryAttributes()
+{
+}
+
+PointerStyle getPointerStyle( const uno::Reference< frame::XModel >& xModel )
+{
+
+ PointerStyle nPointerStyle( PointerStyle::Arrow );
+ try
+ {
+ const uno::Reference< frame::XController > xController( xModel->getCurrentController(), uno::UNO_SET_THROW );
+ const uno::Reference< frame::XFrame > xFrame ( xController->getFrame(), uno::UNO_SET_THROW );
+ const uno::Reference< awt::XWindow > xWindow ( xFrame->getContainerWindow(), uno::UNO_SET_THROW );
+ // why the heck isn't there an XWindowPeer::getPointer, but a setPointer only?
+ const vcl::Window* pWindow = VCLUnoHelper::GetWindow( xWindow );
+ if ( pWindow )
+ nPointerStyle = pWindow->GetSystemWindow()->GetPointer();
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("vbahelper");
+ }
+ return nPointerStyle;
+}
+
+// #FIXME this method looks wrong, shouldn't it just affect calc *or* writer
+// document/frame/window(s) but not both ( and depending on what api called
+// this )
+void setCursorHelper( const uno::Reference< frame::XModel >& xModel, PointerStyle nPointer, bool bOverWrite )
+{
+ ::std::vector< uno::Reference< frame::XController > > aControllers;
+
+ uno::Reference< frame::XModel2 > xModel2( xModel, uno::UNO_QUERY );
+ if ( xModel2.is() )
+ {
+ const uno::Reference< container::XEnumeration > xEnumControllers( xModel2->getControllers(), uno::UNO_SET_THROW );
+ while ( xEnumControllers->hasMoreElements() )
+ {
+ const uno::Reference< frame::XController > xController( xEnumControllers->nextElement(), uno::UNO_QUERY_THROW );
+ aControllers.push_back( xController );
+ }
+ }
+ else
+ {
+ if ( xModel.is() )
+ {
+ const uno::Reference< frame::XController > xController( xModel->getCurrentController(), uno::UNO_SET_THROW );
+ aControllers.push_back( xController );
+ }
+ }
+
+ for ( const auto& rController : aControllers )
+ {
+ const uno::Reference< frame::XFrame > xFrame ( rController->getFrame(), uno::UNO_SET_THROW );
+ const uno::Reference< awt::XWindow > xWindow ( xFrame->getContainerWindow(), uno::UNO_SET_THROW );
+
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
+ SAL_WARN_IF( !pWindow, "vbahelper", "ScVbaApplication::setCursor: no window!" );
+ if ( !pWindow )
+ continue;
+
+ pWindow->GetSystemWindow()->SetPointer( nPointer );
+ pWindow->GetSystemWindow()->EnableChildPointerOverwrite( bOverWrite );
+ }
+}
+
+void setDefaultPropByIntrospection( const uno::Any& aObj, const uno::Any& aValue )
+{
+ uno::Reference< beans::XIntrospectionAccess > xUnoAccess( getIntrospectionAccess( aObj ) );
+
+ // #MAYBE #FIXME sort of a bit of a hack,
+ uno::Reference< script::XDefaultProperty > xDflt( aObj, uno::UNO_QUERY_THROW );
+ uno::Reference< beans::XPropertySet > xPropSet;
+
+ if ( xUnoAccess.is() )
+ xPropSet.set( xUnoAccess->queryAdapter( cppu::UnoType<beans::XPropertySet>::get()), uno::UNO_QUERY);
+
+ if ( !xPropSet.is() )
+ throw uno::RuntimeException();
+
+ xPropSet->setPropertyValue( xDflt->getDefaultPropertyName(), aValue );
+}
+
+uno::Any getPropertyValue( const uno::Sequence< beans::PropertyValue >& aProp, const OUString& aName )
+{
+ auto pProp = std::find_if(aProp.begin(), aProp.end(),
+ [&aName](const beans::PropertyValue& rProp) { return rProp.Name == aName; });
+ if (pProp != aProp.end())
+ return pProp->Value;
+ return uno::Any();
+}
+
+bool setPropertyValue( uno::Sequence< beans::PropertyValue >& aProp, const OUString& aName, const uno::Any& aValue )
+{
+ auto [begin, end] = asNonConstRange(aProp);
+ auto pProp = std::find_if(begin, end,
+ [&aName](const beans::PropertyValue& rProp) { return rProp.Name == aName; });
+ if (pProp != end)
+ {
+ pProp->Value = aValue;
+ return true;
+ }
+ return false;
+}
+
+void setOrAppendPropertyValue( uno::Sequence< beans::PropertyValue >& aProp, const OUString& aName, const uno::Any& aValue )
+{
+ if( setPropertyValue( aProp, aName, aValue ) )
+ return;
+
+ // append the property
+ sal_Int32 nLength = aProp.getLength();
+ aProp.realloc( nLength + 1 );
+ auto pProp = aProp.getArray();
+ pProp[ nLength ].Name = aName;
+ pProp[ nLength ].Value = aValue;
+}
+
+// ====UserFormGeomentryHelper====
+
+UserFormGeometryHelper::UserFormGeometryHelper(
+ const uno::Reference< awt::XControl >& xControl,
+ double fOffsetX, double fOffsetY ) :
+ mfOffsetX( fOffsetX ),
+ mfOffsetY( fOffsetY ),
+ mbDialog( uno::Reference< awt::XDialog >( xControl, uno::UNO_QUERY ).is() )
+{
+ if ( !xControl.is() )
+ throw uno::RuntimeException( "No control is provided!" );
+
+ mxWindow.set( xControl->getPeer(), uno::UNO_QUERY_THROW );
+ mxModelProps.set( xControl->getModel(), uno::UNO_QUERY_THROW );
+ mxUnitConv.set( mxWindow, uno::UNO_QUERY_THROW );
+}
+
+double UserFormGeometryHelper::getLeft() const
+{
+ return implGetPos( false );
+}
+
+void UserFormGeometryHelper::setLeft( double fLeft )
+{
+ implSetPos( fLeft, false );
+}
+
+double UserFormGeometryHelper::getTop() const
+{
+ return implGetPos( true );
+}
+
+void UserFormGeometryHelper::setTop( double fTop )
+{
+ implSetPos( fTop, true );
+}
+
+double UserFormGeometryHelper::getWidth() const
+{
+ return implGetSize( false, true );
+}
+
+void UserFormGeometryHelper::setWidth( double fWidth )
+{
+ implSetSize( fWidth, false, true );
+}
+
+double UserFormGeometryHelper::getHeight() const
+{
+ return implGetSize( true, true );
+}
+
+void UserFormGeometryHelper::setHeight( double fHeight )
+{
+ implSetSize( fHeight, true, true );
+}
+
+double UserFormGeometryHelper::getInnerWidth() const
+{
+ return implGetSize( false, false );
+}
+
+void UserFormGeometryHelper::setInnerWidth( double fWidth )
+{
+ implSetSize( fWidth, false, false );
+}
+
+double UserFormGeometryHelper::getInnerHeight() const
+{
+ return implGetSize( true, false );
+}
+
+void UserFormGeometryHelper::setInnerHeight( double fHeight )
+{
+ implSetSize( fHeight, true, false );
+}
+
+double UserFormGeometryHelper::getOffsetX() const
+{
+ return mfOffsetX;
+}
+
+double UserFormGeometryHelper::getOffsetY() const
+{
+ return mfOffsetY;
+}
+
+constexpr OUStringLiteral saPosXName = u"PositionX";
+constexpr OUStringLiteral saPosYName = u"PositionY";
+constexpr OUStringLiteral saWidthName = u"Width";
+constexpr OUStringLiteral saHeightName = u"Height";
+
+double UserFormGeometryHelper::implGetPos( bool bPosY ) const
+{
+ sal_Int32 nPosAppFont = mxModelProps->getPropertyValue( bPosY ? OUString(saPosYName) : OUString(saPosXName) ).get< sal_Int32 >();
+ // appfont to pixel
+ awt::Point aPosPixel = mxUnitConv->convertPointToPixel( awt::Point( nPosAppFont, nPosAppFont ), util::MeasureUnit::APPFONT );
+ // pixel to VBA points
+ awt::Point aPosPoint = mxUnitConv->convertPointToLogic( aPosPixel, util::MeasureUnit::POINT );
+ return bPosY ? (aPosPoint.Y - mfOffsetY) : (aPosPoint.X - mfOffsetX);
+}
+
+void UserFormGeometryHelper::implSetPos( double fPos, bool bPosY )
+{
+ // convert passed VBA points to pixels
+ sal_Int32 nPosPixel = static_cast< sal_Int32 >( fPos + (bPosY ? mfOffsetY : mfOffsetX) );
+ awt::Point aPosPixel = mxUnitConv->convertPointToPixel( awt::Point( nPosPixel, nPosPixel ), util::MeasureUnit::POINT );
+ // pixel to appfont
+ awt::Point aPosAppFont = mxUnitConv->convertPointToLogic( aPosPixel, util::MeasureUnit::APPFONT );
+ mxModelProps->setPropertyValue( bPosY ? OUString(saPosYName) : OUString(saPosXName), uno::Any( bPosY ? aPosAppFont.Y : aPosAppFont.X ) );
+}
+
+double UserFormGeometryHelper::implGetSize( bool bHeight, bool bOuter ) const
+{
+ sal_Int32 nSizeAppFont = mxModelProps->getPropertyValue( bHeight ? OUString(saHeightName) : OUString(saWidthName) ).get< sal_Int32 >();
+ // appfont to pixel
+ awt::Size aSizePixel = mxUnitConv->convertSizeToPixel( awt::Size( nSizeAppFont, nSizeAppFont ), util::MeasureUnit::APPFONT );
+
+ /* The VBA symbols 'Width' and 'Height' return the outer size including
+ window decoration (in difference to the symbols 'InnerWidth' and
+ 'InnerHeight'), but the window API returns the inner size. */
+ if( mbDialog && bOuter )
+ {
+ if( const vcl::Window* pWindow = VCLUnoHelper::GetWindow( mxWindow ) )
+ {
+ tools::Rectangle aOuterRect = pWindow->GetWindowExtentsRelative( nullptr );
+ aSizePixel = awt::Size( aOuterRect.getWidth(), aOuterRect.getHeight() );
+ }
+ }
+
+ // pixel to VBA points
+ awt::Size aSizePoint = mxUnitConv->convertSizeToLogic( aSizePixel, util::MeasureUnit::POINT );
+ return bHeight ? aSizePoint.Height : aSizePoint.Width;
+}
+
+void UserFormGeometryHelper::implSetSize( double fSize, bool bHeight, bool bOuter )
+{
+ // convert passed VBA points to pixels
+ sal_Int32 nSize = static_cast< sal_Int32 >( fSize );
+ awt::Size aSizePixel = mxUnitConv->convertSizeToPixel( awt::Size( nSize, nSize ), util::MeasureUnit::POINT );
+
+ /* The VBA symbols 'Width' and 'Height' set the outer size (in difference
+ to the symbols 'InnerWidth' and 'InnerHeight'), but the dialog model
+ expects the inner size. We have to remove the window extents from the
+ pixel height to get the same result. */
+ if ( mbDialog && bOuter )
+ {
+ if( const vcl::Window* pWindow = VCLUnoHelper::GetWindow( mxWindow ) )
+ {
+ tools::Rectangle aOuterRect = pWindow->GetWindowExtentsRelative( nullptr );
+ if( !aOuterRect.IsEmpty() )
+ {
+ awt::Rectangle aInnerRect = mxWindow->getPosSize();
+ sal_Int32 nDecorWidth = aOuterRect.getWidth() - aInnerRect.Width;
+ sal_Int32 nDecorHeight = aOuterRect.getHeight() - aInnerRect.Height;
+ aSizePixel.Width = ::std::max< sal_Int32 >( aSizePixel.Width - nDecorWidth, 1 );
+ aSizePixel.Height = ::std::max< sal_Int32 >( aSizePixel.Height - nDecorHeight, 1 );
+ }
+ }
+ }
+
+ awt::Size aSizeAppFont = mxUnitConv->convertSizeToLogic( aSizePixel, util::MeasureUnit::APPFONT );
+ mxModelProps->setPropertyValue( bHeight ? OUString(saHeightName) : OUString(saWidthName), uno::Any( bHeight ? aSizeAppFont.Height : aSizeAppFont.Width ) );
+}
+
+
+double ConcreteXShapeGeometryAttributes::getLeft() const
+{
+ return m_pShapeHelper->getLeft();
+}
+void ConcreteXShapeGeometryAttributes::setLeft( double nLeft )
+{
+ m_pShapeHelper->setLeft( nLeft );
+}
+double ConcreteXShapeGeometryAttributes::getTop() const
+{
+ return m_pShapeHelper->getTop();
+}
+void ConcreteXShapeGeometryAttributes::setTop( double nTop )
+{
+ m_pShapeHelper->setTop( nTop );
+}
+
+double ConcreteXShapeGeometryAttributes::getHeight() const
+{
+ return m_pShapeHelper->getHeight();
+}
+void ConcreteXShapeGeometryAttributes::setHeight( double nHeight )
+{
+ m_pShapeHelper->setHeight( nHeight );
+}
+double ConcreteXShapeGeometryAttributes::getWidth() const
+{
+ return m_pShapeHelper->getWidth();
+}
+void ConcreteXShapeGeometryAttributes::setWidth( double nWidth)
+{
+ m_pShapeHelper->setWidth( nWidth );
+}
+
+
+ShapeHelper::ShapeHelper( const css::uno::Reference< css::drawing::XShape >& _xShape)
+ : xShape( _xShape )
+{
+ if( !xShape.is() )
+ throw css::uno::RuntimeException( "No valid shape for helper" );
+}
+
+double ShapeHelper::getHeight() const
+{
+ return Millimeter::getInPoints(xShape->getSize().Height);
+}
+
+void ShapeHelper::setHeight(double _fheight)
+{
+ css::awt::Size aSize = xShape->getSize();
+ aSize.Height = Millimeter::getInHundredthsOfOneMillimeter(_fheight);
+ xShape->setSize(aSize);
+}
+
+double ShapeHelper::getWidth() const
+{
+ return Millimeter::getInPoints(xShape->getSize().Width);
+}
+
+void ShapeHelper::setWidth(double _fWidth)
+{
+ css::awt::Size aSize = xShape->getSize();
+ aSize.Width = Millimeter::getInHundredthsOfOneMillimeter(_fWidth);
+ xShape->setSize(aSize);
+}
+
+double ShapeHelper::getLeft() const
+{
+ return Millimeter::getInPoints(xShape->getPosition().X);
+}
+
+void ShapeHelper::setLeft(double _fLeft)
+{
+ css::awt::Point aPoint = xShape->getPosition();
+ aPoint.X = Millimeter::getInHundredthsOfOneMillimeter(_fLeft);
+ xShape->setPosition(aPoint);
+}
+
+double ShapeHelper::getTop() const
+{
+ return Millimeter::getInPoints(xShape->getPosition().Y);
+}
+
+void ShapeHelper::setTop(double _fTop)
+{
+ css::awt::Point aPoint = xShape->getPosition();
+ aPoint.Y = Millimeter::getInHundredthsOfOneMillimeter(_fTop);
+ xShape->setPosition(aPoint);
+}
+
+void DebugHelper::basicexception( const css::uno::Exception& ex, ErrCode err, std::u16string_view /*additionalArgument*/ )
+{
+ // #TODO #FIXME ( do we want to support additionalArg here )
+ throw css::script::BasicErrorException( ex.Message, css::uno::Reference< css::uno::XInterface >(), sal_uInt32(err), OUString() );
+}
+
+void DebugHelper::basicexception( ErrCode err, std::u16string_view additionalArgument )
+{
+ basicexception( css::uno::Exception(), err, additionalArgument );
+}
+
+void DebugHelper::basicexception( const css::uno::Exception& ex )
+{
+ basicexception( ex, ERRCODE_BASIC_INTERNAL_ERROR, {} );
+}
+
+void DebugHelper::runtimeexception( ErrCode err )
+{
+ // #TODO #FIXME ( do we want to support additionalArg here )
+ throw css::uno::RuntimeException( css::uno::Exception().Message + " " + OUString::number(sal_uInt32(err)),
+ css::uno::Reference< css::uno::XInterface >() );
+}
+
+Millimeter::Millimeter():m_nMillimeter(0) {}
+
+Millimeter::Millimeter(double mm):m_nMillimeter(mm) {}
+
+void Millimeter::setInPoints(double points)
+{
+ m_nMillimeter = convertPointToMm100(points) / 100.0;
+}
+
+double Millimeter::getInHundredthsOfOneMillimeter() const
+{
+ return m_nMillimeter * 100;
+}
+
+sal_Int32 Millimeter::getInHundredthsOfOneMillimeter(double points)
+{
+ sal_Int32 mm = std::round(convertPointToMm100(points));
+ return mm;
+}
+
+double Millimeter::getInPoints(int _hmm)
+{
+ double points = convertMm100ToPoint<double>(_hmm);
+ return points;
+}
+
+uno::Reference< XHelperInterface > getVBADocument( const uno::Reference< frame::XModel >& xModel )
+{
+ uno::Reference< XHelperInterface > xIf;
+ try
+ {
+ uno::Reference< beans::XPropertySet > xDocProps( xModel, uno::UNO_QUERY_THROW );
+ OUString aCodeName;
+ xDocProps->getPropertyValue( "CodeName" ) >>= aCodeName;
+ xIf = getUnoDocModule( aCodeName, getSfxObjShell( xModel ) );
+ }
+ catch (const uno::Exception&)
+ {
+ }
+ return xIf;
+}
+
+uno::Reference< XHelperInterface > getUnoDocModule( std::u16string_view aModName, SfxObjectShell const * pShell )
+{
+ uno::Reference< XHelperInterface > xIf;
+ if ( pShell )
+ {
+ OUString sProj( "Standard" );
+ // GetBasicManager() causes a SolarMutex assertion failure in some use cases from
+ // Automation, at least when opening a Calc Document through ooo::vba::excel::
+ // XWorkbooks::Open(). Let's see if this check is a good way around that. It does seem that
+ // callers are prepared for this to return null?
+ if (comphelper::Automation::AutomationInvokedZone::isActive())
+ return xIf;
+ BasicManager* pBasMgr = pShell->GetBasicManager();
+ if ( pBasMgr && !pBasMgr->GetName().isEmpty() )
+ sProj = pBasMgr->GetName();
+ if( StarBASIC* pBasic = pShell->GetBasicManager()->GetLib( sProj ) )
+ if( SbModule* pMod = pBasic->FindModule( aModName ) )
+ xIf.set( pMod->GetUnoModule(), uno::UNO_QUERY );
+ }
+ return xIf;
+}
+
+SfxObjectShell* getSfxObjShell( const uno::Reference< frame::XModel >& xModel )
+{
+ SfxObjectShell* pFoundShell = comphelper::getFromUnoTunnel<SfxObjectShell>(xModel);
+ if ( !pFoundShell )
+ throw uno::RuntimeException();
+ return pFoundShell;
+}
+
+} //org
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */