/************************************************************************* * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: vbahelper.cxx,v $ * * $Revision: 1.2 $ * * last change: $Author: rt $ $Date: 2007-04-25 16:07:21 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. * * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2005 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * ************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vbahelper.hxx" #include "tabvwsh.hxx" #include "transobj.hxx" #include "scmod.hxx" using namespace ::com::sun::star; using namespace ::org::openoffice; void unoToSbxValue( SbxVariable* pVar, const uno::Any& aValue ); uno::Any sbxToUnoValue( SbxVariable* pVar ); namespace org { namespace openoffice { // helper method to determine if the view ( calc ) is in print-preview mode 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; } const ::rtl::OUString REPLACE_CELLS_WARNING( RTL_CONSTASCII_USTRINGPARAM( "ReplaceCellsWarning")); const uno::Any& aNULL() { static uno::Any aNULLL = uno::makeAny( uno::Reference< uno::XInterface >() ); return aNULLL; } class PasteCellsWarningReseter { private: bool bInitialWarningState; static uno::Reference< beans::XPropertySet > getGlobalSheetSettings() throw ( uno::RuntimeException ) { static uno::Reference xContext( ::cppu::defaultBootstrap_InitialComponentContext(), uno::UNO_QUERY_THROW ); static uno::Reference xServiceManager( xContext->getServiceManager(), uno::UNO_QUERY_THROW ); static uno::Reference< beans::XPropertySet > xProps( xServiceManager->createInstanceWithContext( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.GlobalSheetSettings" ) ) ,xContext ), uno::UNO_QUERY_THROW ); return xProps; } bool getReplaceCellsWarning() throw ( uno::RuntimeException ) { sal_Bool res = sal_False; getGlobalSheetSettings()->getPropertyValue( REPLACE_CELLS_WARNING ) >>= res; return ( res == sal_True ); } void setReplaceCellsWarning( bool bState ) throw ( uno::RuntimeException ) { getGlobalSheetSettings()->setPropertyValue( REPLACE_CELLS_WARNING, uno::makeAny( bState ) ); } public: PasteCellsWarningReseter() throw ( uno::RuntimeException ) { bInitialWarningState = getReplaceCellsWarning(); if ( bInitialWarningState ) setReplaceCellsWarning( false ); } ~PasteCellsWarningReseter() { if ( bInitialWarningState ) { // don't allow dtor to throw try { setReplaceCellsWarning( true ); } catch ( uno::Exception& /*e*/ ){} } } }; void dispatchRequests (uno::Reference< frame::XModel>& xModel,rtl::OUString & aUrl, uno::Sequence< beans::PropertyValue >& sProps ) { util::URL url ; url.Complete = aUrl; rtl::OUString emptyString = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "" )); uno::Reference xController = xModel->getCurrentController(); uno::Reference xFrame = xController->getFrame(); uno::Reference xDispatchProvider (xFrame,uno::UNO_QUERY_THROW); try { uno::Reference xContext( ::cppu::defaultBootstrap_InitialComponentContext()); if ( !xContext.is() ) { return ; } uno::Reference xServiceManager( xContext->getServiceManager() ); if ( !xServiceManager.is() ) { return ; } uno::Reference xParser( xServiceManager->createInstanceWithContext( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ) ) ,xContext), uno::UNO_QUERY_THROW ); if (!xParser.is()) return; xParser->parseStrict (url); } catch ( ::cppu::BootstrapException & /*e*/ ) { return ; } catch ( uno::Exception & /*e*/ ) { return ; } uno::Reference xDispatcher = xDispatchProvider->queryDispatch(url,emptyString,0); uno::Sequence dispatchProps(1); sal_Int32 nProps = sProps.getLength(); beans::PropertyValue* pDest = dispatchProps.getArray(); if ( nProps ) { dispatchProps.realloc( nProps + 1 ); // need to reaccquire pDest after realloc pDest = dispatchProps.getArray(); beans::PropertyValue* pSrc = sProps.getArray(); for ( sal_Int32 index=0; indexdispatch( url, dispatchProps ); } void dispatchRequests (uno::Reference< frame::XModel>& xModel,rtl::OUString & aUrl) { uno::Sequence dispatchProps; dispatchRequests( xModel, aUrl, dispatchProps ); } void implnPaste() { PasteCellsWarningReseter resetWarningBox; ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); if ( pViewShell ) { pViewShell->PasteFromSystem(); pViewShell->CellContentChanged(); } } void implnCopy() { ScTabViewShell* pViewShell = getCurrentBestViewShell(); if ( pViewShell ) pViewShell->CopyToClip(NULL,false,false,true); } void implnCut() { ScTabViewShell* pViewShell = getCurrentBestViewShell(); if ( pViewShell ) pViewShell->CutToClip( NULL, TRUE ); } void implnPasteSpecial(USHORT nFlags,USHORT nFunction,sal_Bool bSkipEmpty, sal_Bool bTranspose) { PasteCellsWarningReseter resetWarningBox; sal_Bool bAsLink(sal_False), bOtherDoc(sal_False); InsCellCmd eMoveMode = INS_NONE; ScTabViewShell* pTabViewShell = ScTabViewShell::GetActiveViewShell(); if ( !pTabViewShell ) // none active, try next best pTabViewShell = getCurrentBestViewShell(); if ( pTabViewShell ) { ScViewData* pView = pTabViewShell->GetViewData(); Window* pWin = ( pView != NULL ) ? pView->GetActiveWin() : NULL; if ( pView && pWin ) { if ( bAsLink && bOtherDoc ) pTabViewShell->PasteFromSystem(0);//SOT_FORMATSTR_ID_LINK else { ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin ); ScDocument* pDoc = NULL; if ( pOwnClip ) pDoc = pOwnClip->GetDocument(); pTabViewShell->PasteFromClip( nFlags, pDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, eMoveMode, IDF_NONE, TRUE ); pTabViewShell->CellContentChanged(); } } } } bool isRangeShortCut( const ::rtl::OUString& sParam ) { // for a ShortCutRange param, I'd expect the first letter to be //[A-Z] and the last letter to be a digit 0-9 e.g A10, [A1:A10] etc. ::rtl::OString sStr = rtl::OUStringToOString( sParam, RTL_TEXTENCODING_UTF8 ); const sal_Char* pFirst = (const sal_Char*)sStr; const sal_Char* pLast = pFirst + ( sStr.getLength() - 1 ); if ( (( *pFirst >= 'A' && *pFirst <= 'Z' ) || ( *pFirst >= 'a' && *pFirst <= 'Z' ) ) ) if ( ( *pLast >= '0' ) && ( *pLast <= '9' ) ) return true; return false; } uno::Reference< frame::XModel > getCurrentDocument() throw (uno::RuntimeException) { uno::Reference< frame::XModel > xModel; SbxObject* pBasic = dynamic_cast< SbxObject* > ( SFX_APP()->GetBasic() ); SbxObject* basicChosen = pBasic ; if ( basicChosen == NULL) { OSL_TRACE("getModelFromBasic() StarBASIC* is NULL" ); return xModel; } SbxObject* p = pBasic; SbxObject* pParent = p->GetParent(); SbxObject* pParentParent = pParent ? pParent->GetParent() : NULL; if( pParentParent ) { basicChosen = pParentParent; } else if( pParent ) { basicChosen = pParent; } uno::Any aModel; SbxVariable *pCompVar = basicChosen->Find( UniString(RTL_CONSTASCII_USTRINGPARAM("ThisComponent")), SbxCLASS_OBJECT ); if ( pCompVar ) { aModel = sbxToUnoValue( pCompVar ); if ( sal_False == ( aModel >>= xModel ) || !xModel.is() ) { // trying last gasp try the current component uno::Reference xCtx( ::cppu::defaultBootstrap_InitialComponentContext(), uno::UNO_QUERY_THROW ); uno::Reference xSMgr( xCtx->getServiceManager(), uno::UNO_QUERY_THROW ); uno::Reference< frame::XDesktop > xDesktop (xSMgr->createInstanceWithContext(::rtl::OUString::createFromAscii("com.sun.star.frame.Desktop"), xCtx), uno::UNO_QUERY_THROW ); xModel.set( xDesktop->getCurrentComponent(), uno::UNO_QUERY ); if ( !xModel.is() ) { throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Can't extract model from basic ( its obviously not set yet ) therefore don't know the currently selected document") ), uno::Reference< uno::XInterface >() ); } return xModel; } else { OSL_TRACE("Have model ThisComponent points to url %s", ::rtl::OUStringToOString( xModel->getURL(), RTL_TEXTENCODING_ASCII_US ).pData->buffer ); } } else { OSL_TRACE("Failed to get ThisComponent"); throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Can't determine the currently selected document") ), uno::Reference< uno::XInterface >() ); } return xModel; } ScDocShell* getDocShell( css::uno::Reference< css::frame::XModel>& xModel ) { uno::Reference< uno::XInterface > xIf( xModel, uno::UNO_QUERY_THROW ); ScModelObj* pModel = dynamic_cast< ScModelObj* >( xIf.get() ); ScDocShell* pDocShell = NULL; if ( pModel ) pDocShell = (ScDocShell*)pModel->GetEmbeddedObject(); return pDocShell; } ScTabViewShell* getBestViewShell( css::uno::Reference< css::frame::XModel>& xModel ) { ScDocShell* pDocShell = getDocShell( xModel ); if ( pDocShell ) return pDocShell->GetBestViewShell(); return NULL; } ScTabViewShell* getCurrentBestViewShell() { uno::Reference< frame::XModel > xModel = getCurrentDocument(); return getBestViewShell( xModel ); } SfxViewFrame* getCurrentViewFrame() { ScTabViewShell* pViewShell = getCurrentBestViewShell(); if ( pViewShell ) return pViewShell->GetViewFrame(); return NULL; } sal_Int32 OORGBToXLRGB( sal_Int32 nCol ) { 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 = ( (nBlue << 16) | (nGreen << 8) | nRed ); return nRGB; } sal_Int32 XLRGBToOORGB( sal_Int32 nCol ) { 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 = ( (nRed << 16) | (nGreen << 8) | nBlue ); return nRGB; } uno::Any OORGBToXLRGB( const uno::Any& aCol ) { sal_Int32 nCol; aCol >>= nCol; nCol = OORGBToXLRGB( nCol ); return uno::makeAny( nCol ); } uno::Any XLRGBToOORGB( const uno::Any& aCol ) { sal_Int32 nCol; aCol >>= nCol; nCol = XLRGBToOORGB( nCol ); return uno::makeAny( nCol ); } 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 ) { sal_Int32 nTo = 0; sal_Int32 nFrom = 0; sal_Int16 nCopies = 1; sal_Bool bPreview = sal_False; sal_Bool bCollate = sal_False; sal_Bool bSelection = bUseSelection; From >>= nFrom; To >>= nTo; Copies >>= nCopies; Preview >>= bPreview; if ( nCopies > 1 ) // Collate only useful when more that 1 copy Collate >>= bCollate; rtl::OUString sRange( RTL_CONSTASCII_USTRINGPARAM( "-" ) ); rtl::OUString sFileName; if (( nFrom || nTo ) ) { if ( nFrom ) sRange = ( ::rtl::OUString::valueOf( nFrom ) + sRange ); if ( nTo ) sRange += ::rtl::OUString::valueOf( nTo ); } if ( PrToFileName.getValue() ) { PrToFileName >>= sFileName; } ScTabViewShell* pViewShell = getBestViewShell( xModel ); SfxViewFrame* pViewFrame = NULL; if ( pViewShell ) pViewFrame = pViewShell->GetViewFrame(); if ( pViewFrame ) { SfxAllItemSet aArgs( SFX_APP()->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.getLength() ) { SfxStringItem sfxFileName( SID_FILE_NAME, sFileName); aArgs.Put( sfxFileName, sfxFileName.Which() ); } if ( sRange.getLength() ) { 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, sal_False ); aArgs.Put( sfxAsync, sfxAsync.Which() ); SfxDispatcher* pDispatcher = pViewFrame->GetDispatcher(); if ( pDispatcher ) { if ( bPreview ) { if ( !pViewFrame->GetFrame()->IsInPlace() ) { SC_MOD()->InputEnterHandler(); pViewFrame->GetDispatcher()->Execute( SID_VIEWSHELL1, SFX_CALLMODE_SYNCHRON ); while ( isInPrintPreview( pViewFrame ) ) Application::Yield(); } } else pDispatcher->Execute( (USHORT)SID_PRINTDOC, (SfxCallMode)SFX_CALLMODE_SYNCHRON, aArgs ); } } // #FIXME #TODO // 1 Preview ( does such a thing exist in OO.org? ) // 2 ActivePrinter ( how/can we switch a printer via API? ) // 3 PrintToFile ( ms behaviour if this option is specified but no // filename supplied 'PrToFileName' then the user will be prompted ) // 4 Need to check behaviour of Selected sheets with range ( e.g. From & To // values ) in oOO these options are mutually exclusive // 5 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 } } }