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/Introspection.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>
34 #include <comphelper/processfactory.hxx>
36 #include <sfx2/objsh.hxx>
37 #include <sfx2/viewfrm.hxx>
38 #include <sfx2/dispatch.hxx>
39 #include <sfx2/app.hxx>
40 #include <svl/stritem.hxx>
44 #include <basic/sbx.hxx>
45 #include <basic/sbstar.hxx>
46 #include <basic/sbuno.hxx>
47 #include <rtl/math.hxx>
50 #include "vbahelper.hxx"
51 #include "tabvwsh.hxx"
52 #include "transobj.hxx"
54 #include "vbashape.hxx"
55 #include "unonames.hxx"
56 #include "cellsuno.hxx"
57 using namespace ::com::sun::star
;
58 using namespace ::ooo::vba
;
60 #define POINTTO100THMILLIMETERFACTOR 35.27778
68 const double Millimeter::factor
= 35.27778;
70 uno::Reference
< beans::XIntrospectionAccess
>
71 getIntrospectionAccess( const uno::Any
& aObject
) throw (uno::RuntimeException
)
73 static uno::Reference
< beans::XIntrospection
> xIntrospection
;
74 if( !xIntrospection
.is() )
76 uno::Reference
< uno::XComponentContext
> xContext( comphelper::getProcessComponentContext() );
77 xIntrospection
.set( beans::Introspection::create(xContext
) );
79 return xIntrospection
->inspect( aObject
);
82 uno::Reference
< script::XTypeConverter
>
83 getTypeConverter( const uno::Reference
< uno::XComponentContext
>& xContext
) throw (uno::RuntimeException
)
85 static uno::Reference
< script::XTypeConverter
> xTypeConv( script::Converter::create(xContext
) );
88 // helper method to determine if the view ( calc ) is in print-preview mode
89 bool isInPrintPreview( SfxViewFrame
* pView
)
91 sal_uInt16 nViewNo
= SID_VIEWSHELL1
- SID_VIEWSHELL0
;
92 if ( pView
->GetObjectShell()->GetFactory().GetViewFactoryCount() >
93 nViewNo
&& !pView
->GetObjectShell()->IsInPlaceActive() )
95 SfxViewFactory
&rViewFactory
=
96 pView
->GetObjectShell()->GetFactory().GetViewFactory(nViewNo
);
97 if ( pView
->GetCurViewId() == rViewFactory
.GetOrdinal() )
103 const char REPLACE_CELLS_WARNING
[] = "ReplaceCellsWarning";
108 static uno::Any aNULLL
= uno::makeAny( uno::Reference
< uno::XInterface
>() );
112 class PasteCellsWarningReseter
115 bool bInitialWarningState
;
116 static uno::Reference
< sheet::XGlobalSheetSettings
> getGlobalSheetSettings() throw ( uno::RuntimeException
)
118 static uno::Reference
< sheet::XGlobalSheetSettings
> xProps
= sheet::sheet( comphelper::getProcessComponentContext() );
122 bool getReplaceCellsWarning() throw ( uno::RuntimeException
)
124 sal_Bool res
= getGlobalSheetSettings()->getReplaceCellsWarning();
125 return ( res
== sal_True
);
128 void setReplaceCellsWarning( bool bState
) throw ( uno::RuntimeException
)
130 getGlobalSheetSettings()->setReplaceCellsWarning( bState
);
133 PasteCellsWarningReseter() throw ( uno::RuntimeException
)
135 bInitialWarningState
= getReplaceCellsWarning();
136 if ( bInitialWarningState
)
137 setReplaceCellsWarning( false );
139 ~PasteCellsWarningReseter()
141 if ( bInitialWarningState
)
143 // don't allow dtor to throw
146 setReplaceCellsWarning( true );
148 catch (const uno::Exception
&)
155 void dispatchExecute(css::uno::Reference
< css::frame::XModel
>& xModel
, sal_uInt16 nSlot
, SfxCallMode nCall
)
157 ScTabViewShell
* pViewShell
= getBestViewShell( xModel
);
158 SfxViewFrame
* pViewFrame
= NULL
;
160 pViewFrame
= pViewShell
->GetViewFrame();
163 SfxDispatcher
* pDispatcher
= pViewFrame
->GetDispatcher();
166 pDispatcher
->Execute( nSlot
, nCall
);
174 PasteCellsWarningReseter resetWarningBox
;
175 ScTabViewShell
* pViewShell
= getCurrentBestViewShell();
178 pViewShell
->PasteFromSystem();
179 pViewShell
->CellContentChanged();
187 ScTabViewShell
* pViewShell
= getCurrentBestViewShell();
189 pViewShell
->CopyToClip(NULL
,false,false,true);
195 ScTabViewShell
* pViewShell
= getCurrentBestViewShell();
197 pViewShell
->CutToClip( NULL
, sal_True
);
200 void implnPasteSpecial(sal_uInt16 nFlags
,sal_uInt16 nFunction
,sal_Bool bSkipEmpty
, sal_Bool bTranspose
)
202 PasteCellsWarningReseter resetWarningBox
;
203 sal_Bool
bAsLink(false), bOtherDoc(false);
204 InsCellCmd eMoveMode
= INS_NONE
;
206 ScTabViewShell
* pTabViewShell
= ScTabViewShell::GetActiveViewShell();
207 if ( !pTabViewShell
)
208 // none active, try next best
209 pTabViewShell
= getCurrentBestViewShell();
212 ScViewData
* pView
= pTabViewShell
->GetViewData();
213 Window
* pWin
= ( pView
!= NULL
) ? pView
->GetActiveWin() : NULL
;
216 if ( bAsLink
&& bOtherDoc
)
217 pTabViewShell
->PasteFromSystem(0);//SOT_FORMATSTR_ID_LINK
220 ScTransferObj
* pOwnClip
= ScTransferObj::GetOwnClipboard( pWin
);
221 ScDocument
* pDoc
= NULL
;
223 pDoc
= pOwnClip
->GetDocument();
224 pTabViewShell
->PasteFromClip( nFlags
, pDoc
,
225 nFunction
, bSkipEmpty
, bTranspose
, bAsLink
,
226 eMoveMode
, IDF_NONE
, sal_True
);
227 pTabViewShell
->CellContentChanged();
234 uno::Reference
< frame::XModel
>
235 getCurrentDocument() throw (uno::RuntimeException
)
237 uno::Reference
< frame::XModel
> xModel
;
238 SbxObject
* pBasic
= dynamic_cast< SbxObject
* > ( SFX_APP()->GetBasic() );
239 SbxObject
* basicChosen
= pBasic
;
240 if ( basicChosen
== NULL
)
242 OSL_TRACE("getModelFromBasic() StarBASIC* is NULL" );
245 SbxObject
* p
= pBasic
;
246 SbxObject
* pParent
= p
->GetParent();
247 SbxObject
* pParentParent
= pParent
? pParent
->GetParent() : NULL
;
251 basicChosen
= pParentParent
;
255 basicChosen
= pParent
;
260 SbxVariable
*pCompVar
= basicChosen
->Find( "ThisComponent", SbxCLASS_OBJECT
);
264 aModel
= sbxToUnoValue( pCompVar
);
265 if ( false == ( aModel
>>= xModel
) ||
268 uno::Reference
< uno::XComponentContext
> xCtx(
269 comphelper::getProcessComponentContext() );
270 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create(xCtx
);
271 xModel
.set( xDesktop
->getCurrentComponent(), uno::UNO_QUERY
);
274 throw uno::RuntimeException(
275 "Can't extract model from basic ( its obviously not set yet therefore don't know the currently selected document)", uno::Reference
< uno::XInterface
>() );
281 OSL_TRACE("Have model ThisComponent points to url %s",
282 OUStringToOString( xModel
->getURL(),
283 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
288 OSL_TRACE("Failed to get ThisComponent");
289 throw uno::RuntimeException(
290 OUString( "Can't determine the currently selected document" ),
291 uno::Reference
< uno::XInterface
>() );
297 getDocShell( css::uno::Reference
< css::frame::XModel
>& xModel
)
299 uno::Reference
< uno::XInterface
> xIf( xModel
, uno::UNO_QUERY_THROW
);
300 ScModelObj
* pModel
= dynamic_cast< ScModelObj
* >( xIf
.get() );
301 ScDocShell
* pDocShell
= NULL
;
303 pDocShell
= (ScDocShell
*)pModel
->GetEmbeddedObject();
309 getBestViewShell( css::uno::Reference
< css::frame::XModel
>& xModel
)
311 ScDocShell
* pDocShell
= getDocShell( xModel
);
313 return pDocShell
->GetBestViewShell();
318 getCurrentBestViewShell()
320 uno::Reference
< frame::XModel
> xModel
= getCurrentDocument();
321 return getBestViewShell( xModel
);
325 getCurrentViewFrame()
327 ScTabViewShell
* pViewShell
= getCurrentBestViewShell();
329 return pViewShell
->GetViewFrame();
334 OORGBToXLRGB( sal_Int32 nCol
)
336 sal_Int32 nRed
= nCol
;
339 sal_Int32 nGreen
= nCol
;
340 nGreen
&= 0x0000FF00;
342 sal_Int32 nBlue
= nCol
;
344 sal_Int32 nRGB
= ( (nBlue
<< 16) | (nGreen
<< 8) | nRed
);
348 XLRGBToOORGB( sal_Int32 nCol
)
350 sal_Int32 nBlue
= nCol
;
353 sal_Int32 nGreen
= nCol
;
354 nGreen
&= 0x0000FF00;
356 sal_Int32 nRed
= nCol
;
358 sal_Int32 nRGB
= ( (nRed
<< 16) | (nGreen
<< 8) | nBlue
);
362 OORGBToXLRGB( const uno::Any
& aCol
)
366 nCol
= OORGBToXLRGB( nCol
);
367 return uno::makeAny( nCol
);
370 XLRGBToOORGB( const uno::Any
& aCol
)
374 nCol
= XLRGBToOORGB( nCol
);
375 return uno::makeAny( nCol
);
378 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
)
382 sal_Int16 nCopies
= 1;
383 sal_Bool bPreview
= false;
384 sal_Bool bCollate
= false;
385 sal_Bool bSelection
= bUseSelection
;
389 Preview
>>= bPreview
;
390 if ( nCopies
> 1 ) // Collate only useful when more that 1 copy
391 Collate
>>= bCollate
;
393 OUString
sRange( "-" );
396 if (( nFrom
|| nTo
) )
399 sRange
= OUString::number( nFrom
) + sRange
;
401 sRange
+= OUString::number( nTo
);
404 if ( PrToFileName
.getValue() )
406 PrToFileName
>>= sFileName
;
408 ScTabViewShell
* pViewShell
= getBestViewShell( xModel
);
409 SfxViewFrame
* pViewFrame
= NULL
;
411 pViewFrame
= pViewShell
->GetViewFrame();
414 SfxAllItemSet
aArgs( SFX_APP()->GetPool() );
416 SfxBoolItem
sfxCollate( SID_PRINT_COLLATE
, bCollate
);
417 aArgs
.Put( sfxCollate
, sfxCollate
.Which() );
418 SfxInt16Item
sfxCopies( SID_PRINT_COPIES
, nCopies
);
419 aArgs
.Put( sfxCopies
, sfxCopies
.Which() );
420 if ( sFileName
.getLength() )
422 SfxStringItem
sfxFileName( SID_FILE_NAME
, sFileName
);
423 aArgs
.Put( sfxFileName
, sfxFileName
.Which() );
426 if ( sRange
.getLength() )
428 SfxStringItem
sfxRange( SID_PRINT_PAGES
, sRange
);
429 aArgs
.Put( sfxRange
, sfxRange
.Which() );
431 SfxBoolItem
sfxSelection( SID_SELECTION
, bSelection
);
432 aArgs
.Put( sfxSelection
, sfxSelection
.Which() );
433 SfxBoolItem
sfxAsync( SID_ASYNCHRON
, false );
434 aArgs
.Put( sfxAsync
, sfxAsync
.Which() );
435 SfxDispatcher
* pDispatcher
= pViewFrame
->GetDispatcher();
441 if ( !pViewFrame
->GetFrame().IsInPlace() )
443 SC_MOD()->InputEnterHandler();
444 pViewFrame
->GetDispatcher()->Execute( SID_VIEWSHELL1
, SFX_CALLMODE_SYNCHRON
);
445 while ( isInPrintPreview( pViewFrame
) )
446 Application::Yield();
450 pDispatcher
->Execute( (sal_uInt16
)SID_PRINTDOC
, (SfxCallMode
)SFX_CALLMODE_SYNCHRON
, aArgs
);
456 // 1 ActivePrinter ( how/can we switch a printer via API? )
457 // 2 PrintToFile ( ms behaviour if this option is specified but no
458 // filename supplied 'PrToFileName' then the user will be prompted )
459 // 3 Need to check behaviour of Selected sheets with range ( e.g. From & To
460 // values ) in oOO these options are mutually exclusive
461 // 4 There is a pop up to do with transparent objects in the print source
462 // should be able to disable that via configuration for the duration
466 void PrintPreviewHelper( const css::uno::Any
& /*EnableChanges*/, css::uno::Reference
< css::frame::XModel
>& xModel
)
468 dispatchExecute( xModel
, SID_VIEWSHELL1
);
471 OUString
getAnyAsString( const uno::Any
& pvargItem
) throw ( uno::RuntimeException
)
473 uno::Type aType
= pvargItem
.getValueType();
474 uno::TypeClass eTypeClass
= aType
.getTypeClass();
476 switch ( eTypeClass
)
478 case uno::TypeClass_BOOLEAN
:
480 sal_Bool bBool
= false;
482 sString
= OUString::boolean( bBool
);
485 case uno::TypeClass_STRING
:
486 pvargItem
>>= sString
;
488 case uno::TypeClass_FLOAT
:
491 pvargItem
>>= aFloat
;
492 sString
= OUString::number( aFloat
);
495 case uno::TypeClass_DOUBLE
:
498 pvargItem
>>= aDouble
;
499 sString
= OUString::number( aDouble
);
502 case uno::TypeClass_SHORT
:
503 case uno::TypeClass_LONG
:
504 case uno::TypeClass_BYTE
:
508 sString
= OUString::number( aNum
);
512 case uno::TypeClass_HYPER
:
514 sal_Int64 aHyper
= 0;
515 pvargItem
>>= aHyper
;
516 sString
= OUString::number( aHyper
);
520 throw uno::RuntimeException("Invalid type, can't convert", uno::Reference
< uno::XInterface
>() );
527 ContainerUtilities::getUniqueName( const uno::Sequence
< OUString
>& _slist
, const OUString
& _sElementName
, const OUString
& _sSuffixSeparator
)
529 return getUniqueName(_slist
, _sElementName
, _sSuffixSeparator
, sal_Int32(2));
533 ContainerUtilities::getUniqueName( const uno::Sequence
< OUString
>& _slist
, const OUString _sElementName
, const OUString
& _sSuffixSeparator
, sal_Int32 _nStartSuffix
)
535 sal_Int32 a
= _nStartSuffix
;
536 OUString scompname
= _sElementName
;
537 bool bElementexists
= true;
538 sal_Int32 nLen
= _slist
.getLength();
540 return _sElementName
;
542 while (bElementexists
== true)
544 for (sal_Int32 i
= 0; i
< nLen
; i
++)
546 if (FieldInList(_slist
, scompname
) == -1)
551 scompname
= _sElementName
+ _sSuffixSeparator
+ OUString::number( a
++ );
557 ContainerUtilities::FieldInList( const uno::Sequence
< OUString
>& SearchList
, const OUString
& SearchString
)
559 sal_Int32 FieldLen
= SearchList
.getLength();
560 sal_Int32 retvalue
= -1;
561 for (sal_Int32 i
= 0; i
< FieldLen
; i
++)
563 // I wonder why comparing lexicographically is done
564 // when it's a match is whats interesting?
565 //if (SearchList[i].compareTo(SearchString) == 0)
566 if ( SearchList
[i
] == SearchString
)
575 bool NeedEsc(sal_Unicode cCode
)
577 OUString
sEsc(".^$+\\|{}()");
578 return (-1 != sEsc
.indexOf(cCode
));
581 OUString
VBAToRegexp(const OUString
&rIn
, bool bForLike
)
583 OUStringBuffer sResult
;
584 const sal_Unicode
*start
= rIn
.getStr();
585 const sal_Unicode
*end
= start
+ rIn
.getLength();
589 sResult
.append(static_cast<sal_Unicode
>('^'));
596 sResult
.append(static_cast<sal_Unicode
>('.'));
600 sResult
.append(OUString(".*"));
604 sResult
.append(OUString("[0-9]"));
608 sResult
.append(static_cast<sal_Unicode
>('\\'));
609 sResult
.append(*(++start
));
612 // dump the ~ and escape the next characture
614 sResult
.append(static_cast<sal_Unicode
>('\\'));
615 sResult
.append(*start
++);
618 sResult
.append(*start
++);
620 while (start
< end
&& !seenright
)
627 sResult
.append(static_cast<sal_Unicode
>('\\'));
628 sResult
.append(*start
);
631 sResult
.append(*start
);
635 sResult
.append(static_cast<sal_Unicode
>('^'));
639 sResult
.append(static_cast<sal_Unicode
>('\\'));
640 sResult
.append(*start
);
648 sResult
.append(static_cast<sal_Unicode
>('\\'));
649 sResult
.append(*start
++);
654 sResult
.append(static_cast<sal_Unicode
>('$'));
656 return sResult
.makeStringAndClear( );
659 double getPixelTo100thMillimeterConversionFactor( css::uno::Reference
< css::awt::XDevice
>& xDevice
, sal_Bool bVertical
)
661 double fConvertFactor
= 1.0;
664 fConvertFactor
= xDevice
->getInfo().PixelPerMeterY
/100000;
668 fConvertFactor
= xDevice
->getInfo().PixelPerMeterX
/100000;
670 return fConvertFactor
;
673 double PointsToPixels( css::uno::Reference
< css::awt::XDevice
>& xDevice
, double fPoints
, sal_Bool bVertical
)
675 double fConvertFactor
= getPixelTo100thMillimeterConversionFactor( xDevice
, bVertical
);
676 return fPoints
* POINTTO100THMILLIMETERFACTOR
* fConvertFactor
;
678 double PixelsToPoints( css::uno::Reference
< css::awt::XDevice
>& xDevice
, double fPixels
, sal_Bool bVertical
)
680 double fConvertFactor
= getPixelTo100thMillimeterConversionFactor( xDevice
, bVertical
);
681 return (fPixels
/fConvertFactor
)/POINTTO100THMILLIMETERFACTOR
;
684 ConcreteXShapeGeometryAttributes::ConcreteXShapeGeometryAttributes( const css::uno::Reference
< css::uno::XComponentContext
>& xContext
, const css::uno::Reference
< css::drawing::XShape
>& xShape
)
686 m_xShape
= new ScVbaShape( xContext
, xShape
);
689 #define VBA_LEFT "PositionX"
690 #define VBA_TOP "PositionY"
691 UserFormGeometryHelper::UserFormGeometryHelper( const uno::Reference
< uno::XComponentContext
>& /*xContext*/, const uno::Reference
< awt::XControl
>& xControl
)
693 mxModel
.set( xControl
->getModel(), uno::UNO_QUERY_THROW
);
695 double UserFormGeometryHelper::getLeft()
698 mxModel
->getPropertyValue( OUString( VBA_LEFT
) ) >>= nLeft
;
699 return Millimeter::getInPoints( nLeft
);
701 void UserFormGeometryHelper::setLeft( double nLeft
)
703 mxModel
->setPropertyValue( OUString( VBA_LEFT
), uno::makeAny( Millimeter::getInHundredthsOfOneMillimeter( nLeft
) ) );
705 double UserFormGeometryHelper::getTop()
708 mxModel
->getPropertyValue( OUString( VBA_TOP
) ) >>= nTop
;
709 return Millimeter::getInPoints( nTop
);
711 void UserFormGeometryHelper::setTop( double nTop
)
713 mxModel
->setPropertyValue( OUString( VBA_TOP
), uno::makeAny( Millimeter::getInHundredthsOfOneMillimeter( nTop
) ) );
715 double UserFormGeometryHelper::getHeight()
717 sal_Int32 nHeight
= 0;
718 mxModel
->getPropertyValue( OUString( SC_UNONAME_CELLHGT
) ) >>= nHeight
;
719 return Millimeter::getInPoints( nHeight
);
721 void UserFormGeometryHelper::setHeight( double nHeight
)
723 mxModel
->setPropertyValue( OUString( SC_UNONAME_CELLHGT
), uno::makeAny( Millimeter::getInHundredthsOfOneMillimeter( nHeight
) ) );
725 double UserFormGeometryHelper::getWidth()
727 sal_Int32 nWidth
= 0;
728 mxModel
->getPropertyValue( OUString( SC_UNONAME_CELLWID
) ) >>= nWidth
;
729 return Millimeter::getInPoints( nWidth
);
731 void UserFormGeometryHelper::setWidth( double nWidth
)
733 mxModel
->setPropertyValue( OUString( SC_UNONAME_CELLWID
), uno::makeAny( Millimeter::getInHundredthsOfOneMillimeter( nWidth
) ) );
737 ScVbaCellRangeAccess::GetDataSet( ScCellRangeObj
* pRangeObj
)
739 SfxItemSet
* pDataSet
= pRangeObj
? pRangeObj
->GetCurrentDataSet( true ) : NULL
;
747 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */