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 .
19 #include <cppuhelper/bootstrap.hxx>
20 #include <com/sun/star/beans/XPropertySet.hpp>
21 #include <com/sun/star/beans/theIntrospection.hpp>
22 #include <com/sun/star/frame/XDispatchProvider.hpp>
23 #include <com/sun/star/frame/XModel.hpp>
24 #include <com/sun/star/frame/XFrame.hpp>
25 #include <com/sun/star/frame/Desktop.hpp>
26 #include <com/sun/star/frame/XController.hpp>
27 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
28 #include <com/sun/star/script/Converter.hpp>
29 #include <com/sun/star/sheet/GlobalSheetSettings.hpp>
30 #include <com/sun/star/uno/XComponentContext.hpp>
31 #include <com/sun/star/util/XURLTransformer.hpp>
33 #include <comphelper/processfactory.hxx>
35 #include <sfx2/objsh.hxx>
36 #include <sfx2/viewfrm.hxx>
37 #include <sfx2/dispatch.hxx>
38 #include <sfx2/app.hxx>
39 #include <svl/stritem.hxx>
43 #include <basic/sbx.hxx>
44 #include <basic/sbstar.hxx>
45 #include <basic/sbuno.hxx>
46 #include <rtl/math.hxx>
49 #include "vbahelper.hxx"
50 #include "tabvwsh.hxx"
51 #include "transobj.hxx"
53 #include "vbashape.hxx"
54 #include "unonames.hxx"
55 #include "cellsuno.hxx"
56 using namespace ::com::sun::star
;
57 using namespace ::ooo::vba
;
59 #define POINTTO100THMILLIMETERFACTOR 35.27778
66 const double Millimeter::factor
= 35.27778;
68 uno::Reference
< beans::XIntrospectionAccess
>
69 getIntrospectionAccess( const uno::Any
& aObject
) throw (uno::RuntimeException
)
71 static uno::Reference
< beans::XIntrospection
> xIntrospection
;
72 if( !xIntrospection
.is() )
74 uno::Reference
< uno::XComponentContext
> xContext( comphelper::getProcessComponentContext() );
75 xIntrospection
.set( beans::theIntrospection::get(xContext
) );
77 return xIntrospection
->inspect( aObject
);
80 uno::Reference
< script::XTypeConverter
>
81 getTypeConverter( const uno::Reference
< uno::XComponentContext
>& xContext
) throw (uno::RuntimeException
)
83 static uno::Reference
< script::XTypeConverter
> xTypeConv( script::Converter::create(xContext
) );
86 // helper method to determine if the view ( calc ) is in print-preview mode
87 bool isInPrintPreview( SfxViewFrame
* pView
)
89 sal_uInt16 nViewNo
= SID_VIEWSHELL1
- SID_VIEWSHELL0
;
90 if ( pView
->GetObjectShell()->GetFactory().GetViewFactoryCount() >
91 nViewNo
&& !pView
->GetObjectShell()->IsInPlaceActive() )
93 SfxViewFactory
&rViewFactory
=
94 pView
->GetObjectShell()->GetFactory().GetViewFactory(nViewNo
);
95 if ( pView
->GetCurViewId() == rViewFactory
.GetOrdinal() )
101 const char REPLACE_CELLS_WARNING
[] = "ReplaceCellsWarning";
106 static uno::Any aNULLL
= uno::makeAny( uno::Reference
< uno::XInterface
>() );
110 class PasteCellsWarningReseter
113 bool bInitialWarningState
;
114 static uno::Reference
< sheet::XGlobalSheetSettings
> getGlobalSheetSettings() throw ( uno::RuntimeException
)
116 static uno::Reference
< sheet::XGlobalSheetSettings
> xProps
= sheet::sheet( comphelper::getProcessComponentContext() );
120 bool getReplaceCellsWarning() throw ( uno::RuntimeException
)
122 sal_Bool res
= getGlobalSheetSettings()->getReplaceCellsWarning();
123 return ( res
== sal_True
);
126 void setReplaceCellsWarning( bool bState
) throw ( uno::RuntimeException
)
128 getGlobalSheetSettings()->setReplaceCellsWarning( bState
);
131 PasteCellsWarningReseter() throw ( uno::RuntimeException
)
133 bInitialWarningState
= getReplaceCellsWarning();
134 if ( bInitialWarningState
)
135 setReplaceCellsWarning( false );
137 ~PasteCellsWarningReseter()
139 if ( bInitialWarningState
)
141 // don't allow dtor to throw
144 setReplaceCellsWarning( true );
146 catch (const uno::Exception
&)
153 void dispatchExecute(css::uno::Reference
< css::frame::XModel
>& xModel
, sal_uInt16 nSlot
, SfxCallMode nCall
)
155 ScTabViewShell
* pViewShell
= getBestViewShell( xModel
);
156 SfxViewFrame
* pViewFrame
= NULL
;
158 pViewFrame
= pViewShell
->GetViewFrame();
161 SfxDispatcher
* pDispatcher
= pViewFrame
->GetDispatcher();
164 pDispatcher
->Execute( nSlot
, nCall
);
172 PasteCellsWarningReseter resetWarningBox
;
173 ScTabViewShell
* pViewShell
= getCurrentBestViewShell();
176 pViewShell
->PasteFromSystem();
177 pViewShell
->CellContentChanged();
184 ScTabViewShell
* pViewShell
= getCurrentBestViewShell();
186 pViewShell
->CopyToClip(NULL
,false,false,true);
192 ScTabViewShell
* pViewShell
= getCurrentBestViewShell();
194 pViewShell
->CutToClip( NULL
, sal_True
);
197 void implnPasteSpecial(sal_uInt16 nFlags
,sal_uInt16 nFunction
,sal_Bool bSkipEmpty
, sal_Bool bTranspose
)
199 PasteCellsWarningReseter resetWarningBox
;
200 sal_Bool
bAsLink(false), bOtherDoc(false);
201 InsCellCmd eMoveMode
= INS_NONE
;
203 ScTabViewShell
* pTabViewShell
= ScTabViewShell::GetActiveViewShell();
204 if ( !pTabViewShell
)
205 // none active, try next best
206 pTabViewShell
= getCurrentBestViewShell();
209 ScViewData
* pView
= pTabViewShell
->GetViewData();
210 vcl::Window
* pWin
= ( pView
!= NULL
) ? pView
->GetActiveWin() : NULL
;
213 if ( bAsLink
&& bOtherDoc
)
214 pTabViewShell
->PasteFromSystem(0);//SotClipboardFormatId::LINK
217 ScTransferObj
* pOwnClip
= ScTransferObj::GetOwnClipboard( pWin
);
218 ScDocument
* pDoc
= NULL
;
220 pDoc
= pOwnClip
->GetDocument();
221 pTabViewShell
->PasteFromClip( nFlags
, pDoc
,
222 nFunction
, bSkipEmpty
, bTranspose
, bAsLink
,
223 eMoveMode
, IDF_NONE
, sal_True
);
224 pTabViewShell
->CellContentChanged();
231 uno::Reference
< frame::XModel
>
232 getCurrentDocument() throw (uno::RuntimeException
)
234 uno::Reference
< frame::XModel
> xModel
;
235 SbxObject
* pBasic
= dynamic_cast< SbxObject
* > ( SfxGetpApp()->GetBasic() );
236 SbxObject
* basicChosen
= pBasic
;
237 if ( basicChosen
== NULL
)
239 OSL_TRACE("getModelFromBasic() StarBASIC* is NULL" );
242 SbxObject
* p
= pBasic
;
243 SbxObject
* pParent
= p
->GetParent();
244 SbxObject
* pParentParent
= pParent
? pParent
->GetParent() : NULL
;
248 basicChosen
= pParentParent
;
252 basicChosen
= pParent
;
256 SbxVariable
*pCompVar
= basicChosen
->Find( "ThisComponent", SbxCLASS_OBJECT
);
260 aModel
= sbxToUnoValue( pCompVar
);
261 if ( false == ( aModel
>>= xModel
) ||
264 uno::Reference
< uno::XComponentContext
> xCtx(
265 comphelper::getProcessComponentContext() );
266 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create(xCtx
);
267 xModel
.set( xDesktop
->getCurrentComponent(), uno::UNO_QUERY
);
270 throw uno::RuntimeException(
271 "Can't extract model from basic ( its obviously not set yet therefore don't know the currently selected document)" );
277 OSL_TRACE("Have model ThisComponent points to url %s",
278 OUStringToOString( xModel
->getURL(),
279 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
284 OSL_TRACE("Failed to get ThisComponent");
285 throw uno::RuntimeException( "Can't determine the currently selected document" );
291 getDocShell( css::uno::Reference
< css::frame::XModel
>& xModel
)
293 uno::Reference
< uno::XInterface
> xIf( xModel
, uno::UNO_QUERY_THROW
);
294 ScModelObj
* pModel
= dynamic_cast< ScModelObj
* >( xIf
.get() );
295 ScDocShell
* pDocShell
= NULL
;
297 pDocShell
= (ScDocShell
*)pModel
->GetEmbeddedObject();
303 getBestViewShell( css::uno::Reference
< css::frame::XModel
>& xModel
)
305 ScDocShell
* pDocShell
= getDocShell( xModel
);
307 return pDocShell
->GetBestViewShell();
312 getCurrentBestViewShell()
314 uno::Reference
< frame::XModel
> xModel
= getCurrentDocument();
315 return getBestViewShell( xModel
);
319 getCurrentViewFrame()
321 ScTabViewShell
* pViewShell
= getCurrentBestViewShell();
323 return pViewShell
->GetViewFrame();
328 OORGBToXLRGB( sal_Int32 nCol
)
330 sal_Int32 nRed
= nCol
;
333 sal_Int32 nGreen
= nCol
;
334 nGreen
&= 0x0000FF00;
336 sal_Int32 nBlue
= nCol
;
338 sal_Int32 nRGB
= ( (nBlue
<< 16) | (nGreen
<< 8) | nRed
);
342 XLRGBToOORGB( sal_Int32 nCol
)
344 sal_Int32 nBlue
= nCol
;
347 sal_Int32 nGreen
= nCol
;
348 nGreen
&= 0x0000FF00;
350 sal_Int32 nRed
= nCol
;
352 sal_Int32 nRGB
= ( (nRed
<< 16) | (nGreen
<< 8) | nBlue
);
356 OORGBToXLRGB( const uno::Any
& aCol
)
360 nCol
= OORGBToXLRGB( nCol
);
361 return uno::makeAny( nCol
);
364 XLRGBToOORGB( const uno::Any
& aCol
)
368 nCol
= XLRGBToOORGB( nCol
);
369 return uno::makeAny( nCol
);
372 void PrintOutHelper( 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
, css::uno::Reference
< frame::XModel
>& xModel
, sal_Bool bUseSelection
)
376 sal_Int16 nCopies
= 1;
377 sal_Bool bPreview
= false;
378 sal_Bool bCollate
= false;
379 sal_Bool bSelection
= bUseSelection
;
383 Preview
>>= bPreview
;
384 if ( nCopies
> 1 ) // Collate only useful when more that 1 copy
385 Collate
>>= bCollate
;
387 OUString
sRange( "-" );
390 if (( nFrom
|| nTo
) )
393 sRange
= OUString::number( nFrom
) + sRange
;
395 sRange
+= OUString::number( nTo
);
398 if ( PrToFileName
.getValue() )
400 PrToFileName
>>= sFileName
;
402 ScTabViewShell
* pViewShell
= getBestViewShell( xModel
);
403 SfxViewFrame
* pViewFrame
= NULL
;
405 pViewFrame
= pViewShell
->GetViewFrame();
408 SfxAllItemSet
aArgs( SfxGetpApp()->GetPool() );
410 SfxBoolItem
sfxCollate( SID_PRINT_COLLATE
, bCollate
);
411 aArgs
.Put( sfxCollate
, sfxCollate
.Which() );
412 SfxInt16Item
sfxCopies( SID_PRINT_COPIES
, nCopies
);
413 aArgs
.Put( sfxCopies
, sfxCopies
.Which() );
414 if ( sFileName
.getLength() )
416 SfxStringItem
sfxFileName( SID_FILE_NAME
, sFileName
);
417 aArgs
.Put( sfxFileName
, sfxFileName
.Which() );
420 if ( sRange
.getLength() )
422 SfxStringItem
sfxRange( SID_PRINT_PAGES
, sRange
);
423 aArgs
.Put( sfxRange
, sfxRange
.Which() );
425 SfxBoolItem
sfxSelection( SID_SELECTION
, bSelection
);
426 aArgs
.Put( sfxSelection
, sfxSelection
.Which() );
427 SfxBoolItem
sfxAsync( SID_ASYNCHRON
, false );
428 aArgs
.Put( sfxAsync
, sfxAsync
.Which() );
429 SfxDispatcher
* pDispatcher
= pViewFrame
->GetDispatcher();
435 if ( !pViewFrame
->GetFrame().IsInPlace() )
437 SC_MOD()->InputEnterHandler();
438 pViewFrame
->GetDispatcher()->Execute( SID_VIEWSHELL1
, SfxCallMode::SYNCHRON
);
439 while ( isInPrintPreview( pViewFrame
) )
440 Application::Yield();
444 pDispatcher
->Execute( (sal_uInt16
)SID_PRINTDOC
, (SfxCallMode
)SfxCallMode::SYNCHRON
, aArgs
);
450 // 1 ActivePrinter ( how/can we switch a printer via API? )
451 // 2 PrintToFile ( ms behaviour if this option is specified but no
452 // filename supplied 'PrToFileName' then the user will be prompted )
453 // 3 Need to check behaviour of Selected sheets with range ( e.g. From & To
454 // values ) in oOO these options are mutually exclusive
455 // 4 There is a pop up to do with transparent objects in the print source
456 // should be able to disable that via configuration for the duration
460 void PrintPreviewHelper( const css::uno::Any
& /*EnableChanges*/, css::uno::Reference
< css::frame::XModel
>& xModel
)
462 dispatchExecute( xModel
, SID_VIEWSHELL1
);
465 OUString
getAnyAsString( const uno::Any
& pvargItem
) throw ( uno::RuntimeException
)
467 uno::Type aType
= pvargItem
.getValueType();
468 uno::TypeClass eTypeClass
= aType
.getTypeClass();
470 switch ( eTypeClass
)
472 case uno::TypeClass_BOOLEAN
:
474 sal_Bool bBool
= false;
476 sString
= OUString::boolean( bBool
);
479 case uno::TypeClass_STRING
:
480 pvargItem
>>= sString
;
482 case uno::TypeClass_FLOAT
:
485 pvargItem
>>= aFloat
;
486 sString
= OUString::number( aFloat
);
489 case uno::TypeClass_DOUBLE
:
492 pvargItem
>>= aDouble
;
493 sString
= OUString::number( aDouble
);
496 case uno::TypeClass_SHORT
:
497 case uno::TypeClass_LONG
:
498 case uno::TypeClass_BYTE
:
502 sString
= OUString::number( aNum
);
506 case uno::TypeClass_HYPER
:
508 sal_Int64 aHyper
= 0;
509 pvargItem
>>= aHyper
;
510 sString
= OUString::number( aHyper
);
514 throw uno::RuntimeException("Invalid type, can't convert" );
520 ContainerUtilities::getUniqueName( const uno::Sequence
< OUString
>& _slist
, const OUString
& _sElementName
, const OUString
& _sSuffixSeparator
)
522 return getUniqueName(_slist
, _sElementName
, _sSuffixSeparator
, sal_Int32(2));
526 ContainerUtilities::getUniqueName( const uno::Sequence
< OUString
>& _slist
, const OUString _sElementName
, const OUString
& _sSuffixSeparator
, sal_Int32 _nStartSuffix
)
528 sal_Int32 a
= _nStartSuffix
;
529 OUString scompname
= _sElementName
;
530 bool bElementexists
= true;
531 sal_Int32 nLen
= _slist
.getLength();
533 return _sElementName
;
535 while (bElementexists
== true)
537 for (sal_Int32 i
= 0; i
< nLen
; i
++)
539 if (FieldInList(_slist
, scompname
) == -1)
544 scompname
= _sElementName
+ _sSuffixSeparator
+ OUString::number( a
++ );
550 ContainerUtilities::FieldInList( const uno::Sequence
< OUString
>& SearchList
, const OUString
& SearchString
)
552 sal_Int32 FieldLen
= SearchList
.getLength();
553 sal_Int32 retvalue
= -1;
554 for (sal_Int32 i
= 0; i
< FieldLen
; i
++)
556 // I wonder why comparing lexicographically is done
557 // when it's a match is whats interesting?
558 //if (SearchList[i].compareTo(SearchString) == 0)
559 if ( SearchList
[i
] == SearchString
)
568 bool NeedEsc(sal_Unicode cCode
)
570 OUString
sEsc(".^$+\\|{}()");
571 return (-1 != sEsc
.indexOf(cCode
));
574 OUString
VBAToRegexp(const OUString
&rIn
, bool bForLike
)
576 OUStringBuffer sResult
;
577 const sal_Unicode
*start
= rIn
.getStr();
578 const sal_Unicode
*end
= start
+ rIn
.getLength();
593 sResult
.append(".*");
597 sResult
.append("[0-9]");
601 sResult
.append('\\');
602 sResult
.append(*(++start
));
605 // dump the ~ and escape the next characture
607 sResult
.append('\\');
608 sResult
.append(*start
++);
611 sResult
.append(*start
++);
613 while (start
< end
&& !seenright
)
620 sResult
.append('\\');
621 sResult
.append(*start
);
624 sResult
.append(*start
);
632 sResult
.append('\\');
633 sResult
.append(*start
);
641 sResult
.append('\\');
642 sResult
.append(*start
++);
649 return sResult
.makeStringAndClear( );
652 double getPixelTo100thMillimeterConversionFactor( css::uno::Reference
< css::awt::XDevice
>& xDevice
, sal_Bool bVertical
)
654 double fConvertFactor
= 1.0;
657 fConvertFactor
= xDevice
->getInfo().PixelPerMeterY
/100000;
661 fConvertFactor
= xDevice
->getInfo().PixelPerMeterX
/100000;
663 return fConvertFactor
;
666 double PointsToPixels( css::uno::Reference
< css::awt::XDevice
>& xDevice
, double fPoints
, sal_Bool bVertical
)
668 double fConvertFactor
= getPixelTo100thMillimeterConversionFactor( xDevice
, bVertical
);
669 return fPoints
* POINTTO100THMILLIMETERFACTOR
* fConvertFactor
;
671 double PixelsToPoints( css::uno::Reference
< css::awt::XDevice
>& xDevice
, double fPixels
, sal_Bool bVertical
)
673 double fConvertFactor
= getPixelTo100thMillimeterConversionFactor( xDevice
, bVertical
);
674 return (fPixels
/fConvertFactor
)/POINTTO100THMILLIMETERFACTOR
;
677 ConcreteXShapeGeometryAttributes::ConcreteXShapeGeometryAttributes( const css::uno::Reference
< css::uno::XComponentContext
>& xContext
, const css::uno::Reference
< css::drawing::XShape
>& xShape
)
679 m_xShape
= new ScVbaShape( xContext
, xShape
);
682 #define VBA_LEFT "PositionX"
683 #define VBA_TOP "PositionY"
684 UserFormGeometryHelper::UserFormGeometryHelper( const uno::Reference
< uno::XComponentContext
>& /*xContext*/, const uno::Reference
< awt::XControl
>& xControl
)
686 mxModel
.set( xControl
->getModel(), uno::UNO_QUERY_THROW
);
688 double UserFormGeometryHelper::getLeft()
691 mxModel
->getPropertyValue( OUString( VBA_LEFT
) ) >>= nLeft
;
692 return Millimeter::getInPoints( nLeft
);
694 void UserFormGeometryHelper::setLeft( double nLeft
)
696 mxModel
->setPropertyValue( OUString( VBA_LEFT
), uno::makeAny( Millimeter::getInHundredthsOfOneMillimeter( nLeft
) ) );
698 double UserFormGeometryHelper::getTop()
701 mxModel
->getPropertyValue( OUString( VBA_TOP
) ) >>= nTop
;
702 return Millimeter::getInPoints( nTop
);
704 void UserFormGeometryHelper::setTop( double nTop
)
706 mxModel
->setPropertyValue( OUString( VBA_TOP
), uno::makeAny( Millimeter::getInHundredthsOfOneMillimeter( nTop
) ) );
708 double UserFormGeometryHelper::getHeight()
710 sal_Int32 nHeight
= 0;
711 mxModel
->getPropertyValue( OUString( SC_UNONAME_CELLHGT
) ) >>= nHeight
;
712 return Millimeter::getInPoints( nHeight
);
714 void UserFormGeometryHelper::setHeight( double nHeight
)
716 mxModel
->setPropertyValue( OUString( SC_UNONAME_CELLHGT
), uno::makeAny( Millimeter::getInHundredthsOfOneMillimeter( nHeight
) ) );
718 double UserFormGeometryHelper::getWidth()
720 sal_Int32 nWidth
= 0;
721 mxModel
->getPropertyValue( OUString( SC_UNONAME_CELLWID
) ) >>= nWidth
;
722 return Millimeter::getInPoints( nWidth
);
724 void UserFormGeometryHelper::setWidth( double nWidth
)
726 mxModel
->setPropertyValue( OUString( SC_UNONAME_CELLWID
), uno::makeAny( Millimeter::getInHundredthsOfOneMillimeter( nWidth
) ) );
730 ScVbaCellRangeAccess::GetDataSet( ScCellRangeObj
* pRangeObj
)
732 SfxItemSet
* pDataSet
= pRangeObj
? pRangeObj
->GetCurrentDataSet( true ) : NULL
;
740 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */