diff options
-rw-r--r-- | filter/inc/filter/msfilter/escherex.hxx | 21 | ||||
-rw-r--r-- | filter/inc/filter/msfilter/msocximex.hxx | 82 | ||||
-rw-r--r-- | filter/inc/filter/msfilter/svxmsbas.hxx | 18 | ||||
-rw-r--r-- | filter/source/msfilter/eschesdo.cxx | 13 | ||||
-rw-r--r-- | filter/source/msfilter/makefile.mk | 2 | ||||
-rw-r--r-- | filter/source/msfilter/msocximex.cxx | 945 | ||||
-rw-r--r-- | filter/source/msfilter/msoleexp.cxx | 5 | ||||
-rw-r--r-- | filter/source/msfilter/msvbasic.cxx | 812 | ||||
-rw-r--r-- | filter/source/msfilter/msvbasic.hxx | 11 | ||||
-rw-r--r-- | filter/source/msfilter/svxmsbas.cxx | 113 | ||||
-rwxr-xr-x[-rw-r--r--] | oox/inc/oox/ole/vbacontrol.hxx | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | oox/source/ole/vbacontrol.cxx | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | oox/source/ole/vbaproject.cxx | 2 |
13 files changed, 1574 insertions, 457 deletions
diff --git a/filter/inc/filter/msfilter/escherex.hxx b/filter/inc/filter/msfilter/escherex.hxx index 51058e2eabd8..6bf0e8b9c200 100644 --- a/filter/inc/filter/msfilter/escherex.hxx +++ b/filter/inc/filter/msfilter/escherex.hxx @@ -45,6 +45,7 @@ #include <com/sun/star/drawing/BitmapMode.hpp> #include <com/sun/star/drawing/Hatch.hpp> #include <svx/msdffdef.hxx> +#include <memory> #include "filter/msfilter/msfilterdllapi.h" /*Record Name FBT-Value Instance Contents Wrd Exl PPt Ver*/ @@ -1305,6 +1306,19 @@ public: const Rectangle& rRect ) = 0; }; +class InteractionInfo +{ + bool mbHasInteraction; + std::auto_ptr<SvMemoryStream> mpHyperlinkRecord; + InteractionInfo(); +public: + InteractionInfo( SvMemoryStream* pStream, bool bInteraction ) : mbHasInteraction( bInteraction ) + { + mpHyperlinkRecord.reset( pStream ); + } + bool hasInteraction() { return mbHasInteraction; } + const std::auto_ptr< SvMemoryStream >& getHyperlinkRecord() { return mpHyperlinkRecord; } +}; class EscherExHostAppData { @@ -1312,14 +1326,17 @@ private: EscherExClientAnchor_Base* pClientAnchor; EscherExClientRecord_Base* pClientData; EscherExClientRecord_Base* pClientTextbox; + InteractionInfo* pInteractionInfo; // ignore single shape if entire pages are written BOOL bDontWriteShape; public: EscherExHostAppData() : pClientAnchor(0), pClientData(0), - pClientTextbox(0), bDontWriteShape(FALSE) + pClientTextbox(0), pInteractionInfo(0), bDontWriteShape(FALSE) {} + void SetInteractionInfo( InteractionInfo* p ) + { pInteractionInfo = p; } void SetClientAnchor( EscherExClientAnchor_Base* p ) { pClientAnchor = p; } void SetClientData( EscherExClientRecord_Base* p ) @@ -1328,6 +1345,8 @@ public: { pClientTextbox = p; } void SetDontWriteShape( BOOL b ) { bDontWriteShape = b; } + InteractionInfo* GetInteractionInfo() const + { return pInteractionInfo; } EscherExClientAnchor_Base* GetClientAnchor() const { return pClientAnchor; } EscherExClientRecord_Base* GetClientData() const diff --git a/filter/inc/filter/msfilter/msocximex.hxx b/filter/inc/filter/msfilter/msocximex.hxx index a106b40d2852..ef82cfe6d35a 100644 --- a/filter/inc/filter/msfilter/msocximex.hxx +++ b/filter/inc/filter/msfilter/msocximex.hxx @@ -29,6 +29,7 @@ #include <sot/storage.hxx> #include <tools/debug.hxx> +#include <com/sun/star/graphic/XGraphicObject.hpp> //!! no such defines in global namespaces - it will break other existing code that uses the same define!! //#ifndef C2U @@ -287,7 +288,10 @@ public: bool mbVisible; UniString sName; UniString msToolTip; + UniString msParentName; OCX_FontData aFontData; + rtl::OUString msCtrlSource; + rtl::OUString msRowSource; SfxObjectShell *pDocSh; protected: @@ -324,14 +328,13 @@ public: nMultiState(0), nValueLen(0), nCaptionLen(0), nVertPos(1), nHorzPos(7), nSpecialEffect(2), nIcon(0), nPicture(0), nAccelerator(0), nGroupNameLen(0), pValue(0), pCaption(0), pGroupName(0), nIconLen(0), pIcon(0), - nPictureLen(0), pPicture(0) {} + nPictureLen(0) {} ~OCX_ModernControl() { if (pValue) delete[] pValue; if (pCaption) delete[] pCaption; if (pGroupName) delete[] pGroupName; if (pIcon) delete[] pIcon; - if (pPicture) delete[] pPicture; } sal_Bool Read(SotStorageStream *pS); @@ -412,7 +415,8 @@ public: sal_uInt8 pPictureHeader[20]; sal_uInt32 nPictureLen; - sal_uInt8 *pPicture; + ::rtl::OUString sImageUrl; + com::sun::star::uno::Reference< com::sun::star::graphic::XGraphicObject> mxGrfObj; }; @@ -461,6 +465,7 @@ public: bool bAutoSize; ::rtl::OUString sImageUrl; + com::sun::star::uno::Reference< com::sun::star::graphic::XGraphicObject> mxGrfObj; sal_Bool Read(SotStorageStream *pS); using OCX_Control::Import; // to not hide the other two import methods @@ -485,6 +490,8 @@ struct ContainerRecord ::rtl::OUString cName; ::rtl::OUString controlTip; + ::rtl::OUString sCtrlSource; + ::rtl::OUString sRowSource; sal_uInt32 nTop; sal_uInt32 nLeft; @@ -499,54 +506,8 @@ typedef std::vector<OCX_Control*>::iterator CtrlIterator; typedef std::vector<OCX_Control*>::const_iterator CtrlIteratorConst; typedef std::vector<OCX_Control*> CtrlList; - - -class RBGroup -{ - public: - RBGroup():mRBGroupPos(0){} - RBGroup(sal_uInt16& groupPos ):mRBGroupPos(groupPos){} - sal_Int16 tabPos() const { return mRBGroupPos; } - std::vector<OCX_Control*>::size_type numControls() - { return mpControls.size(); } - std::vector<OCX_Control*>& controls() { return mpControls; } - - void add(OCX_Control* pRB); - private: - sal_uInt16 mRBGroupPos; - std::vector<OCX_Control*> mpControls; -}; - -typedef ::std::hash_map < ::rtl::OUString, RBGroup*, ::rtl::OUStringHash, - ::std::equal_to< ::rtl::OUString > > RBGroupHash; -typedef std::vector<RBGroup*>::iterator GroupIterator; - class OCX_OptionButton; -class RBGroupManager -{ -public: - RBGroupManager( String& defaultName ); - ~RBGroupManager(); - - CtrlList insertGroupsIntoControlList( const CtrlList& sourceList ); - void addRadioButton( OCX_OptionButton* pRButton ); -private: - - void addSeperator( std::vector< OCX_Control* >& dest ); - void copyList( std::vector< OCX_Control* >& src, - std::vector< OCX_Control* >& dest, - bool addGroupSeperator ); - - RBGroupHash rbGroups; - String mSDefaultName; - std::vector< RBGroup* > groupList; - sal_uInt16 numRadioButtons; -}; - - - - class OCX_ContainerControl : public OCX_Control { public: @@ -572,8 +533,9 @@ public: SotStorageStreamRef getContainerStream() { return mContainerStream; } virtual void ProcessControl( OCX_Control* pControl, SvStorageStream* pS, ContainerRecord& rec ); - bool createFromContainerRecord( const ContainerRecord& record, + bool createFromContainerRecord( ContainerRecord& record, OCX_Control*& ); + SotStorageStreamRef getContainedControlsStream(){ return mContainedControlsStream; } protected: // This class not meant to be instantiated // needs to be subclassed @@ -585,10 +547,10 @@ protected: OCX_Control* pParent = NULL ); rtl::OUString createSubStreamName( const sal_uInt32& subStorageID ); - RBGroupManager rbGroupMgr; com::sun::star::uno::Reference< com::sun::star::container::XNameContainer > mxParent; std::vector<OCX_Control*> mpControls; + std::hash_map<sal_uInt16, sal_uInt16> mActiveXIDMap; SotStorageRef mContainerStorage; SotStorageStreamRef mContainerStream; SotStorageStreamRef mContainedControlsStream; @@ -856,7 +818,6 @@ public: { delete[] pCaption; delete[] pIcon; - delete[] pPicture; } virtual sal_Bool Read(SvStorageStream *pS); @@ -920,7 +881,8 @@ public: sal_uInt8 pPictureHeader[20]; sal_uInt32 nPictureLen; - sal_uInt8 *pPicture; + ::rtl::OUString sImageUrl; + com::sun::star::uno::Reference< com::sun::star::graphic::XGraphicObject> mxGrfObj; private: com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext> mxCtx; @@ -959,7 +921,8 @@ public: OCX_OptionButton() : OCX_ModernControl(rtl::OUString::createFromAscii("OptionButton")) { msFormType = rtl::OUString::createFromAscii("com.sun.star.form.component.RadioButton"); - msDialogType = rtl::OUString::createFromAscii("com.sun.star.awt.UnoControlRadioButtonModel"); + //msDialogType = rtl::OUString::createFromAscii("com.sun.star.awt.UnoControlRadioButtonModel"); + msDialogType = rtl::OUString::createFromAscii("com.sun.star.form.component.RadioButton"); mnBackColor = 0x80000005L; mnForeColor = 0x80000008L; aFontData.SetHasAlign(TRUE); @@ -1060,7 +1023,7 @@ class OCX_ComboBox : public OCX_ModernControl public: OCX_ComboBox() : OCX_ModernControl(rtl::OUString::createFromAscii("ComboBox")){ msFormType = rtl::OUString::createFromAscii("com.sun.star.form.component.ComboBox"); - msDialogType = rtl::OUString::createFromAscii("com.sun.star.awt.UnoControlComboBoxModel"); + msDialogType = rtl::OUString::createFromAscii("com.sun.star.form.component.ComboBox"); mnBackColor = 0x80000005; mnForeColor = 0x80000008; nBorderColor = 0x80000006; @@ -1085,7 +1048,8 @@ class OCX_ListBox : public OCX_ModernControl public: OCX_ListBox() : OCX_ModernControl(rtl::OUString::createFromAscii("ListBox")){ msFormType = rtl::OUString::createFromAscii("com.sun.star.form.component.ListBox"); - msDialogType = rtl::OUString::createFromAscii("com.sun.star.awt.UnoControlListBoxModel"); + //msDialogType = rtl::OUString::createFromAscii("com.sun.star.awt.UnoControlListBoxModel"); + msDialogType = rtl::OUString::createFromAscii("com.sun.star.form.component.ListBox"); mnBackColor = 0x80000005; mnForeColor = 0x80000008; nBorderColor = 0x80000006; @@ -1113,7 +1077,7 @@ public: fEnabled(1), fLocked(0), fBackStyle(1), fWordWrap(0), fAutoSize(0), nCaptionLen(0), nVertPos(1), nHorzPos(7), nMousePointer(0), nPicture(0), nAccelerator(0), nIcon(0), pCaption(0), nIconLen(0), pIcon(0), nPictureLen(0), - pPicture(0), mbTakeFocus( true ) + mbTakeFocus( true ) { msFormType = rtl::OUString::createFromAscii("com.sun.star.form.component.CommandButton"); msDialogType = rtl::OUString::createFromAscii("com.sun.star.awt.UnoControlButtonModel"); @@ -1124,7 +1088,6 @@ public: ~OCX_CommandButton() { if (pCaption) delete[] pCaption; if (pIcon) delete[] pIcon; - if (pPicture) delete[] pPicture; } sal_Bool Read(SotStorageStream *pS); @@ -1167,7 +1130,8 @@ public: sal_uInt8 pPictureHeader[20]; sal_uInt32 nPictureLen; - sal_uInt8 *pPicture; + ::rtl::OUString sImageUrl; + com::sun::star::uno::Reference< com::sun::star::graphic::XGraphicObject> mxGrfObj; bool mbTakeFocus; diff --git a/filter/inc/filter/msfilter/svxmsbas.hxx b/filter/inc/filter/msfilter/svxmsbas.hxx index 716c6788989c..2fdf935821c6 100644 --- a/filter/inc/filter/msfilter/svxmsbas.hxx +++ b/filter/inc/filter/msfilter/svxmsbas.hxx @@ -32,6 +32,8 @@ #include "filter/msfilter/msfilterdllapi.h" #include <sot/storage.hxx> +#include <map> +#include <hash_map> class SfxObjectShell; @@ -50,6 +52,12 @@ class SfxObjectShell; * probably what the user expects to see when viewing the code */ +typedef std::hash_map< sal_Int32, String > ObjIdToName; + +typedef std::map< String, ObjIdToName > ControlAttributeInfo; + +class VBA_Impl; + class MSFILTER_DLLPUBLIC SvxImportMSVBasic { public: @@ -76,23 +84,31 @@ public: // check if the MS-VBA-Storage exist in the RootStorage of the DocShell. // If it exist, then return the WarningId for loosing the information. + + const ControlAttributeInfo& ControlNameForObjectId(){ return m_ModuleNameToObjIdHash; } static ULONG GetSaveWarningOfMSVBAStorage( SfxObjectShell &rDocS ); static String GetMSBasicStorageName(); + rtl::OUString GetVBAProjectName() { return msProjectName; } private: SotStorageRef xRoot; SfxObjectShell &rDocSh; BOOL bImport; BOOL bCopy; + ControlAttributeInfo m_ModuleNameToObjIdHash; + MSFILTER_DLLPRIVATE void extractAttribute( const String& rAttribute, const String& rModName ); MSFILTER_DLLPRIVATE BOOL ImportCode_Impl( const String& rStorageName, const String &rSubStorageName, const std::vector< String >& codeNames, BOOL bAsComment, BOOL bStripped); MSFILTER_DLLPRIVATE bool ImportForms_Impl(const String& rStorageName, - const String &rSubStorageName); + const String &rSubStorageName, BOOL bVBAMode); MSFILTER_DLLPRIVATE BOOL CopyStorage_Impl( const String& rStorageName, const String &rSubStorageName); + rtl::OUString msProjectName; + MSFILTER_DLLPRIVATE BOOL ImportCode_Impl( VBA_Impl&, const std::vector< String >&, BOOL, BOOL ); + MSFILTER_DLLPRIVATE bool ImportForms_Impl( VBA_Impl&, const String&, const String&, BOOL); }; #endif diff --git a/filter/source/msfilter/eschesdo.cxx b/filter/source/msfilter/eschesdo.cxx index 0844f153dd4d..d34945cb896b 100644 --- a/filter/source/msfilter/eschesdo.cxx +++ b/filter/source/msfilter/eschesdo.cxx @@ -245,6 +245,19 @@ UINT32 ImplEESdrWriter::ImplWriteShape( ImplEESdrObject& rObj, // #i51348# shape name if( aShapeName.Len() > 0 ) aPropOpt.AddOpt( ESCHER_Prop_wzName, aShapeName ); + if ( InteractionInfo* pInteraction = mpHostAppData->GetInteractionInfo() ) + { + const std::auto_ptr< SvMemoryStream >& pMemStrm = pInteraction->getHyperlinkRecord(); + if ( pMemStrm.get() ) + { + pMemStrm->ObjectOwnsMemory( FALSE ); + sal_uInt8* pBuf = (sal_uInt8*) pMemStrm->GetData(); + sal_uInt32 nSize = pMemStrm->Seek( STREAM_SEEK_TO_END ); + aPropOpt.AddOpt( ESCHER_Prop_pihlShape, sal_False, nSize, pBuf, nSize );; + } + if ( pInteraction->hasInteraction() ) + aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x00080008 ); + } if ( rObj.GetType().EqualsAscii( "drawing.Custom" ) ) { diff --git a/filter/source/msfilter/makefile.mk b/filter/source/msfilter/makefile.mk index 7780529b5580..c59a1262b8e2 100644 --- a/filter/source/msfilter/makefile.mk +++ b/filter/source/msfilter/makefile.mk @@ -53,6 +53,7 @@ SLOFILES= \ $(SLO)$/svdfppt.obj \ $(SLO)$/svxmsbas2.obj \ $(SLO)$/msvbahelper.obj \ + $(SLO)$/mstoolbar.obj\ SHL1TARGET= msfilter$(DLLPOSTFIX) SHL1IMPLIB= i$(TARGET) @@ -61,6 +62,7 @@ SHL1USE_EXPORTS=name SHL1STDLIBS= \ $(EDITENGLIB) \ $(SVXCORELIB) \ + $(SVTOOLLIB) \ $(SFX2LIB) \ $(XMLOFFLIB) \ $(BASEGFXLIB) \ diff --git a/filter/source/msfilter/msocximex.cxx b/filter/source/msfilter/msocximex.cxx index 248affc540c1..37575c656d20 100644 --- a/filter/source/msfilter/msocximex.cxx +++ b/filter/source/msfilter/msocximex.cxx @@ -45,6 +45,10 @@ #include <com/sun/star/drawing/XDrawPageSupplier.hpp> #include <com/sun/star/form/XFormsSupplier.hpp> #include <com/sun/star/form/XForm.hpp> +#include <com/sun/star/form/binding/XBindableValue.hpp> +#include <com/sun/star/form/binding/XValueBinding.hpp> +#include <com/sun/star/form/binding/XListEntrySink.hpp> +#include <com/sun/star/form/binding/XListEntrySource.hpp> #include <com/sun/star/form/FormComponentType.hpp> #include <com/sun/star/awt/FontWeight.hpp> #include <com/sun/star/awt/FontSlant.hpp> @@ -69,6 +73,21 @@ #include <com/sun/star/ucb/XSimpleFileAccess.hpp> #include <algorithm> #include <memory> +#include <com/sun/star/graphic/GraphicObject.hpp> +#include <com/sun/star/graphic/XGraphicProvider.hpp> +#include <com/sun/star/graphic/XGraphic.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <comphelper/componentcontext.hxx> +#include <unotools/streamwrap.hxx> + +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/table/XCellRange.hpp> +#include <com/sun/star/table/CellRangeAddress.hpp> +#include <com/sun/star/table/CellAddress.hpp> +#include <com/sun/star/sheet/XSpreadsheetView.hpp> +#include <com/sun/star/sheet/XCellRangeAddressable.hpp> +#include <com/sun/star/sheet/XCellRangeReferrer.hpp> +#include <svtools/filterutils.hxx> #ifndef C2S #define C2S(cChar) String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(cChar)) @@ -83,6 +102,7 @@ using namespace cppu; #define WW8_ASCII2STR(s) String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(s)) +#define GRAPHOBJ_URLPREFIX "vnd.sun.star.GraphicObject:" static char sWW8_form[] = "WW-Standard"; @@ -111,127 +131,49 @@ long ReadAlign(SvStorageStream *pS, long nPos, int nAmount) return 0; } - // NP - Images in controls in OO2.0/SO8 exist as links, e.g. they are not part of the document so are // referenced externally. On import from ms document try to save images for controls here. // Images are stored in directory called temp in the user installation directory. Next version of OO/SO // hopefully will address this issue and allow a choice e.g. images for controls to be stored as links // or embeded in the document. - -// [out]location path to the stream to where the image is to be stored, -// if same name exists in folder then this function calcuates a new name -// [in] data raw bytes of image to be stored. -// [in] dataLen no. byte to be stored -// -// returns, true if successful - -bool storePictureInFileSystem( OUString& location, sal_uInt8* data, sal_uInt32 dataLen ) -{ - bool result = true; - OUString origPath = location; - try - { - uno::Reference<lang::XMultiServiceFactory > xMSF( ::comphelper::getProcessServiceFactory(), - uno::UNO_QUERY_THROW ); - uno::Reference< com::sun::star::ucb::XSimpleFileAccess> xSFA( xMSF->createInstance( - S2U("com.sun.star.ucb.SimpleFileAccess" ) ), - uno::UNO_QUERY_THROW ); - OUString ext; - sal_Int32 index = 0; - while ( xSFA->exists( location ) ) - { - ext = OUString::valueOf( ++index ); - location = origPath + ext; - } - - SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( location, STREAM_WRITE | STREAM_TRUNC ); - if ( pStream ) - { - pStream->Write(data, dataLen); - delete pStream; - } - else - { - result = false; - } - } - catch( uno::Exception& ) - { - result = false; - } - return result; -} - -// NP - Images in controls in OO2.0/SO8 exist as links, e.g. they are not part of the document so are -// referenced externally. On import from ms document try to save images from controls here so this -// at least a macro programmer has a chance to accessed them manually later. Next version of OO/SO -// hopefully will address this issue. -// Images will be stored in a top level folder in the document package, folder is named "MigratedImages" - -// [in] pDocSh* the document shell. -// [in] name name of stream image to stored in. -// [in] data raw bytes of image to be stored. -// [in] dataLen no. byte to be stored - -bool storePictureInDoc( SfxObjectShell* pDocSh, OUString& name, sal_uInt8* data, sal_uInt32 dataLen ) +uno::Reference< graphic::XGraphicObject> lcl_readGraphicObject( SotStorageStream *pS ) { - uno::Reference < embed::XStorage > xStor; - if (pDocSh) + uno::Reference< graphic::XGraphicObject > xGrfObj; + uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); + if( xServiceManager.is() ) { - xStor = pDocSh->GetStorage(); - if( xStor.is() ) + try { - try + // use the GraphicProvider service to get the XGraphic + uno::Reference< graphic::XGraphicProvider > xGraphProvider( + xServiceManager->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.graphic.GraphicProvider" ) ), uno::UNO_QUERY ); + if( xGraphProvider.is() ) { - uno::Reference< embed::XStorage > xPictures = xStor->openStorageElement( - OUString( RTL_CONSTASCII_USTRINGPARAM( "MigratedImages" ) ), - embed::ElementModes::READWRITE ); - uno::Reference< beans::XPropertySet > xPropSet( xPictures, uno::UNO_QUERY ); - - // Set media type of folder MigratedImages to something ( that is unknown ) so that - // it will get copied to exported OO/SO format after SaveAs - if ( xPropSet.is() ) - { - OUString aMediaType = C2U("MigrationImages"); - uno::Any a; - a <<= aMediaType; - xPropSet->setPropertyValue( C2U("MediaType"), a ); - } - - uno::Reference< io::XStream > xObjReplStr = xPictures->openStreamElement( - name, - embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE ); - uno::Reference< io::XOutputStream > xOutStream( xObjReplStr->getOutputStream(), uno::UNO_QUERY_THROW ); - uno::Sequence< sal_Int8 > imageBytes( (sal_Int8*)data, dataLen ); - xOutStream->writeBytes( imageBytes ); - xOutStream->closeOutput(); - - uno::Reference< embed::XTransactedObject > xTransact( xPictures, uno::UNO_QUERY ); - if ( xTransact.is() ) + uno::Reference< io::XInputStream > xStream( new utl::OInputStreamWrapper( *pS ) ); + if( xStream.is() ) { - xTransact->commit(); + uno::Sequence< beans::PropertyValue > aMediaProps( 1 ); + aMediaProps[0].Name = ::rtl::OUString::createFromAscii( "InputStream" ); + aMediaProps[0].Value <<= xStream; + uno::Reference< graphic::XGraphic > xGraphic = xGraphProvider->queryGraphic( aMediaProps ); + if( xGraphic.is() ) + { + // create an XGraphicObject + ::comphelper::ComponentContext aContext( xServiceManager ); + xGrfObj = graphic::GraphicObject::create( aContext.getUNOContext() ); + xGrfObj->setGraphic(xGraphic); + } } } - catch( uno::Exception& ) - { - return false; - } - } - else + catch( uno::Exception& ) { - // no storage something wrong - return false; } } - else - { - //No doc shell - return false; - } - return true; + return xGrfObj; } + long WriteAlign(SvStorageStream *pS, int nAmount) { if (long nAlign = pS->Tell() % nAmount) @@ -394,35 +336,11 @@ void lclReadCharArray( SvStorageStream& rStrm, char*& rpcCharArr, sal_uInt32 nLe */ OUString lclCreateOUString( const char* pcCharArr, sal_uInt32 nLenFld ) { - OUStringBuffer aBuffer; sal_uInt32 nBufSize = lclGetBufferSize( nLenFld ); if( lclIsCompressed( nLenFld ) ) - { - // buffer contains compressed Unicode, not encoded bytestring - sal_Int32 nStrLen = static_cast< sal_Int32 >( nBufSize ); - aBuffer.setLength( nStrLen ); - const char* pcCurrChar = pcCharArr; - for( sal_Int32 nChar = 0; nChar < nStrLen; ++nChar, ++pcCurrChar ) - /* *pcCurrChar may contain negative values and therefore MUST be - casted to unsigned char, before assigned to a sal_Unicode. */ - aBuffer.setCharAt( nChar, static_cast< unsigned char >( *pcCurrChar ) ); - } - else - { - // buffer contains Little-Endian Unicode - sal_Int32 nStrLen = static_cast< sal_Int32 >( nBufSize ) / 2; - aBuffer.setLength( nStrLen ); - const char* pcCurrChar = pcCharArr; - for( sal_Int32 nChar = 0; nChar < nStrLen; ++nChar ) - { - /* *pcCurrChar may contain negative values and therefore MUST be - casted to unsigned char, before assigned to a sal_Unicode. */ - sal_Unicode cChar = static_cast< unsigned char >( *pcCurrChar++ ); - cChar |= (static_cast< unsigned char >( *pcCurrChar++ ) << 8); - aBuffer.setCharAt( nChar, cChar ); - } - } - return aBuffer.makeStringAndClear(); + return svt::BinFilterUtils::CreateOUStringFromStringArray( pcCharArr, nBufSize ); + + return svt::BinFilterUtils::CreateOUStringFromUniStringArray( pcCharArr, nBufSize ); } // export --------------------------------------------------------------------- @@ -542,8 +460,129 @@ const sal_uInt16 TOGGLEBUTTON = (sal_uInt16)0x1C; const sal_uInt16 SCROLLBAR = (sal_uInt16)0x2F; const sal_uInt16 MULTIPAGE = (sal_uInt16)0x39; +// The IDs with bit 0x8000 set appear to be generated. +// It looks like these ID's are used with the non-toolbox [1] +// ActiveX controls that can be present in a Userform +// ( note: RefEdit seems to be an exception ) +// In UserForm::Read just before the Container record starts +// you will notice there can be sometimes trailing records, +// it seems that these records have a 1:1 relationship with the non-toolbox +// controls present in the Userform. An id in the trailing record +// seems to identify the specific ActiveX control and an artificial nTypeIdent +// e.g. 0x8000, 0x8001 etc. is created so as to be able to associate +// the ActiveX control when referenced later +// [1] Such ActiveX controls are added via Tools/AddionalControls +// menu + +// create a fixed set of those special id(s) +// ahem, we can only read one Progress bars at the moment so.... const sal_uInt16 PROGRESSBAR = (sal_uInt16)0x8000; +// A set of IDs from the trailing records mentioned above that seem to +// identify the following ActiveX controls +// Currently we only can process ( in a limited way ) the ProgressBar +// the other ID's are for reference ( & future ) + +// RefEdit control {00024512-0000-0000-c000-000000000046} +const sal_uInt8 aRefEditID[] = +{ +0x12, 0x45, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, +}; + +// Microsoft ProgressBar Control, version 6.0 {35053A22-8589-11D1-B16A-00C0F0283628} +const sal_uInt8 aProgressID[] = +{ +0x22, 0x3a, 0x05, 0x35, 0x89, 0x85, 0xd1, 0x11, 0xb1, 0x6a, 0x00, 0xc0, 0xf0, 0x28, 0x36, 0x28, +}; + +// Calendar Control 10.0 +const sal_uInt8 aCalendarID[] = +{ +0x2b, 0xc9, 0x27, 0x8e, 0x64, 0x12, 0x1c, 0x10, 0x8a, 0x2f, 0x04, 0x02, 0x24, 0x00, 0x9c, 0x02, +}; + + +// Microsoft ImageComboxBox Control, version 6.0 {DD9DA666-8594-11D1-B16A-00C0F0283628} +const sal_uInt8 aImageComboID[] = +{ +0x66, 0xa6, 0x9d, 0xdd, 0x94, 0x85, 0xd1, 0x11, 0xb1, 0x6a, 0x00, 0xc0, 0xf0, 0x28, 0x36, 0x28, +}; + +// Microsoft ImageList Control, version 6.0 {2C247F23-8591-11D1-B16A-00C0F0283628} +const sal_uInt8 aImageListID[] = +{ +0x23, 0x7f, 0x24, 0x2c, 0x91, 0x85, 0xd1, 0x11, 0xb1, 0x6a, 0x00, 0xc0, 0xf0, 0x28, 0x36, 0x28, +}; + +// Microsoft Slider Control, version 6.0 {F08DF954-8592-11D1-B16A-00C0F0283628} +const sal_uInt8 aSliderID[] = +{ +0x54, 0xf9, 0x8d, 0xf0, 0x92, 0x85, 0xd1, 0x11, 0xb1, 0x6a, 0x00, 0xc0, 0xf0, 0x28, 0x36, 0x28, +}; + +// Microsoft StatusBar Control, version 6.0 {8E3867A3-8586-11D1-B16A-00C0F0283628} +const sal_uInt8 aStatusBarID[] = +{ +0xa3, 0x67, 0x38, 0x8e, 0x86, 0x85, 0xd1, 0x11, 0xb1, 0x6a, 0x00, 0xc0, 0xf0, 0x28, 0x36, 0x28, +}; + +// Microsoft Office Chart 10.0 +const sal_uInt8 aChartSpaceID[] = +{ +0x46, 0xe5, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, +}; + +const sal_Int16 ActiveXIDLen = 0x10; // CLSID len +const sal_Int16 ActiveXIDBlockLen = 0x30; // the block len that contains the CLSID + +bool lcl_handleActiveXControl( SvStorageStream *pS, sal_uInt16& nTypeID ) +{ + nTypeID = 0; // Illegal ActiveX ID + bool bRes = false; + sal_uInt16 nIdentifier, nFixedAreaLen; + *pS >> nIdentifier; + *pS >> nFixedAreaLen; + pS->SeekRel( ( nFixedAreaLen - ActiveXIDBlockLen ) ); + sal_uInt8 aID[ ActiveXIDLen ]; + if ( !pS->IsEof() ) + { + pS->Read( aID, ActiveXIDLen ); + pS->SeekRel( ActiveXIDBlockLen - ActiveXIDLen ); // read remainer of record + if ( memcmp( aID, aProgressID, ActiveXIDLen ) == 0 ) + { + nTypeID = PROGRESSBAR; + OSL_TRACE("Found supported ***PROGRESSBAR*** ActiveX control"); + bRes = true; + } +#if (OSL_DEBUG_LEVEL > 0) + // If we really want to process these more controls we should put them in + // a list or array and have a single loop testing each id. For the moment + // as we only can process PROGRESSBAR, not much point doing that until + // we add support for at least another activex control + + else if ( memcmp( aID, aCalendarID, ActiveXIDLen ) == 0 ) + OSL_TRACE("Found unsupported ***CALENDAR*** ActiveX control"); + else if ( memcmp( aID, aRefEditID, ActiveXIDLen ) == 0 ) + OSL_TRACE("Found unsupported ***REFEDIT*** ActiveX control"); + else if ( memcmp( aID, aImageComboID, ActiveXIDLen ) == 0 ) + OSL_TRACE("Found unsupported ***IMAGECOMBO*** ActiveX control"); + else if ( memcmp( aID, aImageListID, ActiveXIDLen ) == 0 ) + OSL_TRACE("Found unsupported ***IMAGELIST*** ActiveX control"); + else if ( memcmp( aID, aChartSpaceID, ActiveXIDLen ) == 0 ) + OSL_TRACE("Found unsupported ***CHARTSPACE*** ActiveX control"); + else if ( memcmp( aID, aSliderID, ActiveXIDLen ) == 0 ) + OSL_TRACE("Found unsupported ***SLIDER*** ActiveX control"); + else if ( memcmp( aID, aStatusBarID, ActiveXIDLen ) == 0 ) + OSL_TRACE("Found unsupported ***STATUSBAR*** ActiveX control"); +#endif + else + { + OSL_TRACE("Unknown activeX ID !"); + } + } + return bRes; +} + typedef std::vector< ContainerRecord > ContainerRecordList; class ContainerRecReader @@ -618,6 +657,8 @@ class ContainerRecReader // control type if( nContentFlags & 0x00000080 ) *pS >> rec.nTypeIdent; + if( nContentFlags & 0x00000200 ) + pS->SeekRel( 4 ); // Grouping? // length of infotip sal_uInt32 nTipLen = 0; if( nContentFlags & 0x00000800 ) @@ -692,14 +733,22 @@ class ContainerRecReader if( nCtrlSrcBufSize > 0 ) { ReadAlign( pS, pS->Tell() - nStartPos, 4 ); - pS->SeekRel( nCtrlSrcBufSize ); + std::auto_ptr< sal_Char > pCtrlSrcName; + pCtrlSrcName.reset( new sal_Char[ nCtrlSrcBufSize ] ); + pS->Read( pCtrlSrcName.get(), nCtrlSrcBufSize ); + rec.sCtrlSource = lclCreateOUString( pCtrlSrcName.get(), nCtrlSrcLen ); + OSL_TRACE("*** *** *** ControlSourceName -> %s ", rtl::OUStringToOString( rec.sCtrlSource, RTL_TEXTENCODING_UTF8 ).getStr() ); } // row source name sal_uInt32 nRowSrcBufSize = lclGetBufferSize( nRowSrcLen ); if( nRowSrcBufSize > 0 ) { ReadAlign( pS, pS->Tell() - nStartPos, 4 ); - pS->SeekRel( nRowSrcBufSize ); + std::auto_ptr< sal_Char > pRowSrcName; + pRowSrcName.reset( new sal_Char[ nRowSrcBufSize ] ); + pS->Read( pRowSrcName.get(), nRowSrcBufSize ); + rec.sRowSource = lclCreateOUString( pRowSrcName.get(), nRowSrcLen ); + OSL_TRACE("*** *** *** RowSourceName -> %s ", rtl::OUStringToOString( rec.sRowSource, RTL_TEXTENCODING_UTF8 ).getStr() ); } // seek to end of data @@ -716,6 +765,13 @@ class ContainerRecReader pControl->pDocSh = pContainerControl->pDocSh; pContainerControl->ProcessControl( pControl, pS, rec ); } + else if ( rec.nTypeIdent & 0x8000 ) + { + // Skip ActiveX Controls we can't import + SotStorageStreamRef oStream = pContainerControl->getContainedControlsStream(); + ULONG nStrmPos = oStream->Tell(); + oStream->Seek( nStrmPos + rec.nSubStreamLen ); + } else { DBG_ERROR("Terminating import, unexpected error"); @@ -736,6 +792,11 @@ class ContainerRecReader { sal_uInt8 aUnknown11[4]; pS->Read(aUnknown11, sizeof(aUnknown11)); + // discovered a dialog with value of 0xFF for aUnknown11 + // needed an extra 4 bytes to offset correctly into the control + // records. Valid test or coincidence ? + if ( aUnknown11[1] == 0xFF ) + pS->Read( aUnknown11, sizeof(aUnknown11)); return true; } @@ -810,176 +871,6 @@ class ContainerRecordReaderFac // ============================================================================ -void RBGroup::add(OCX_Control* pRB) -{ - // The tab index for the group is calculated as - // the lowest tab index found in the list of RadioButtons - if ( pRB->mnTabPos < mRBGroupPos ) - { - mRBGroupPos = pRB->mnTabPos; - CtrlIterator aEnd = mpControls.end(); - for (CtrlIterator aIter = mpControls.begin(); aIter != aEnd; ++ aIter ) - { - (*aIter)->mnTabPos = mRBGroupPos; - } - } - mpControls.push_back( pRB ); -} - -struct SortGroupByTabPos -{ - bool operator()( const RBGroup* a, const RBGroup* b ) - { - return a->tabPos() < b->tabPos(); - } -}; - -RBGroupManager::RBGroupManager( String& defaultName ):mSDefaultName( defaultName ), - numRadioButtons(0) -{ - groupList.reserve( 8 ); // reserve far more than we expect -} - -RBGroupManager::~RBGroupManager() -{ - for ( GroupIterator gIter=groupList.begin(); gIter!=groupList.end(); ++gIter ) - { - delete( *gIter ); - } -} - -// Loose description of the method below ( I sure there is a better way to do -// this ) -// In order to "fake" MS grouping behavior for OptionButtons the OptionButtons -// in the same group need to have consecutive tab indices ( regardless of the -// imported tab indices of the RadioButtons ). Additionally if two -// groups of OptionButtons end up having all consecutive indices they -// will be treated as a single group by OpenOffice. In this case -// a dummy seperator control needs to be inserted between the groups. -// -// This method returns a new list "destinationList" containing the controls -// passed in "sourceList" and the OptionButtons contained in the various -// Groups maintained by this class. -// Controls are ordered in the destination list by tab index. -// Each RadioButtonGroup has a tab index associated with it. -// ( Tab index of a RadioGroup is determined as the tab index of the -// OptionButton control with the lowest tab index in the group ) - - -void RBGroupManager::addRadioButton( OCX_OptionButton* pRButton ) -{ - if ( pRButton ) - { - OUString groupName = mSDefaultName; - if ( pRButton->nGroupNameLen ) - { - groupName = - lclCreateOUString(pRButton->pGroupName, - pRButton->nGroupNameLen); - } - ++numRadioButtons; - RBGroupHash::iterator iter = rbGroups.find( groupName ); - if ( iter != rbGroups.end() ) - { - iter->second->controls().push_back( pRButton ); - } - else - { - RBGroup* newGroup = new RBGroup(pRButton->mnTabPos); - newGroup->controls().push_back( pRButton ); - rbGroups[ groupName ] = newGroup; - groupList.push_back( newGroup ); - } - - } -} - -CtrlList RBGroupManager::insertGroupsIntoControlList( const CtrlList& sourceList ) -{ - ::std::sort( groupList.begin(), groupList.end(), SortGroupByTabPos() ); - std::vector<OCX_Control*> destinationList; - if ( groupList.size() ) - { - destinationList.reserve( sourceList.size() + numRadioButtons ); - - GroupIterator groupEnd = groupList.end(); - CtrlIteratorConst sourceEnd = sourceList.end(); - - size_t prevGroupListSize = 0; - - CtrlIteratorConst containees = sourceList.begin(); - GroupIterator groupIter=groupList.begin(); - while ( containees != sourceEnd || - groupIter != groupEnd ) - { - bool addGroupSeperator = false; - if ( containees != sourceEnd ) - { - if ( groupIter != groupEnd ) - { - sal_Int16 groupTabPos = (*groupIter)->tabPos(); - if ( (*containees)->mnTabPos >= groupTabPos ) - { - if ( !(destinationList.size() >= prevGroupListSize )) - { - addGroupSeperator = true; - } - copyList( (*groupIter)->controls(), destinationList, addGroupSeperator ); - ++groupIter; - - prevGroupListSize = destinationList.size(); - } - } - destinationList.push_back(*containees); - ++containees; - } - else - { - if ( groupIter != groupEnd ) - { - if ( !(destinationList.size() > prevGroupListSize )) - { - addGroupSeperator = true; - } - copyList( (*groupIter)->controls(), destinationList, addGroupSeperator ); - ++groupIter; - prevGroupListSize = destinationList.size(); - } - } - } - } - else - { - destinationList = sourceList; - } - return destinationList; - -} - - -void RBGroupManager::addSeperator( std::vector< OCX_Control* >& dest ) -{ - OCX_Control* seperator = new OCX_CommandButton; - seperator->SetInDialog(true); - seperator->sName = C2S("GroupSeperator"); - dest.push_back( seperator ); -} - -void RBGroupManager::copyList( std::vector< OCX_Control* >& src, - std::vector< OCX_Control* >& dest, - bool addGroupSeperator ) -{ - if ( addGroupSeperator ) - { - addSeperator( dest ); - } - - for ( CtrlIterator rbIter = src.begin(); rbIter != src.end(); ++rbIter ) - { - dest.push_back( *rbIter ); - } -} - class OCX_UserFormLabel : public OCX_Label { public: @@ -1146,6 +1037,9 @@ sal_Bool OCX_Control::Import( sal_Bool OCX_Control::Import(uno::Reference<container::XNameContainer> &rDialog ) { + uno::Reference<beans::XPropertySet > xDlgProps( rDialog, uno::UNO_QUERY); + + uno::Reference<lang::XMultiServiceFactory> xFactory(rDialog, uno::UNO_QUERY); @@ -1158,11 +1052,15 @@ sal_Bool OCX_Control::Import(uno::Reference<container::XNameContainer> &rDialog if (!xModel.is()) return sal_False; + sal_Bool bVBA = sal_False; /* #147900# sometimes insertion of a control fails due to existing name, do not break entire form import then... */ try { rDialog->insertByName(sName, uno::makeAny(xModel)); + if ( xDlgProps.is() ) + xDlgProps->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("VBAForm") ) ) >>= bVBA; + } catch( uno::Exception& ) { @@ -1180,14 +1078,29 @@ sal_Bool OCX_Control::Import(uno::Reference<container::XNameContainer> &rDialog return sal_False; uno::Any aTmp; - aTmp <<= sal_Int32((mnLeft * 2) / 100); - xPropSet->setPropertyValue(WW8_ASCII2STR("PositionX"), aTmp); - aTmp <<= sal_Int32((mnTop * 2) / 100); - xPropSet->setPropertyValue(WW8_ASCII2STR("PositionY"), aTmp); - aTmp <<= sal_Int32((nWidth * 2) / 100); - xPropSet->setPropertyValue(WW8_ASCII2STR("Width"), aTmp); - aTmp <<= sal_Int32((nHeight * 2) / 100); - xPropSet->setPropertyValue(WW8_ASCII2STR("Height"), aTmp); + + if ( !bVBA ) + { + aTmp <<= sal_Int32((mnLeft * 2) / 100); + xPropSet->setPropertyValue(WW8_ASCII2STR("PositionX"), aTmp); + aTmp <<= sal_Int32((mnTop * 2) / 100); + xPropSet->setPropertyValue(WW8_ASCII2STR("PositionY"), aTmp); + aTmp <<= sal_Int32((nWidth * 2) / 100); + xPropSet->setPropertyValue(WW8_ASCII2STR("Width"), aTmp); + aTmp <<= sal_Int32((nHeight * 2) / 100); + xPropSet->setPropertyValue(WW8_ASCII2STR("Height"), aTmp); + } + else + { + aTmp <<= sal_Int32(mnLeft); // 100thmm + xPropSet->setPropertyValue(WW8_ASCII2STR("PositionX"), aTmp); + aTmp <<= sal_Int32(mnTop); //100th mm + xPropSet->setPropertyValue(WW8_ASCII2STR("PositionY"), aTmp); + aTmp <<= sal_Int32(nWidth); // 100thmm + xPropSet->setPropertyValue(WW8_ASCII2STR("Width"), aTmp); + aTmp <<= sal_Int32(nHeight); //100th mm + xPropSet->setPropertyValue(WW8_ASCII2STR("Height"), aTmp); + } if ( msToolTip.Len() > 0 ) xPropSet->setPropertyValue(WW8_ASCII2STR("HelpText"), uno::Any(OUString(msToolTip))); @@ -1402,6 +1315,12 @@ sal_Bool OCX_CommandButton::Import( com::sun::star::uno::Reference< rPropSet->setPropertyValue( WW8_ASCII2STR( "FocusOnClick" ), aTmp ); aFontData.Import(rPropSet); + + if ( sImageUrl.getLength() ) + { + aTmp <<= sImageUrl; + rPropSet->setPropertyValue( WW8_ASCII2STR("ImageURL"), aTmp); + } return sal_True; } @@ -1649,6 +1568,99 @@ sal_Bool OCX_ImageButton::Export(SvStorageRef &rObj, return WriteContents(xContents,rPropSet,rSize); } +bool lcl_isNamedRange( const rtl::OUString& sAddress, uno::Reference< frame::XModel >& xModel, table::CellRangeAddress& aAddress ) +{ + bool bRes = false; + const static rtl::OUString sNamedRanges( RTL_CONSTASCII_USTRINGPARAM("NamedRanges")); + uno::Reference< sheet::XCellRangeReferrer > xReferrer; + try + { + uno::Reference< beans::XPropertySet > xPropSet( xModel, uno::UNO_QUERY_THROW ); + uno::Reference< container::XNameAccess > xNamed( xPropSet->getPropertyValue( sNamedRanges ), uno::UNO_QUERY_THROW ); + xReferrer.set ( xNamed->getByName( sAddress ), uno::UNO_QUERY ); + } + catch( uno::Exception& /*e*/ ) + { + // do nothing + } + if ( xReferrer.is() ) + { + uno::Reference< sheet::XCellRangeAddressable > xRangeAddressable( xReferrer->getReferredCells(), uno::UNO_QUERY ); + if ( xRangeAddressable.is() ) + { + aAddress = xRangeAddressable->getRangeAddress(); + bRes = true; + } + } + return bRes; +} + +void lcl_ApplyListSourceAndBindableStuff( uno::Reference< frame::XModel >& xModel, const uno::Reference< beans::XPropertySet >& rPropSet, const rtl::OUString& rsCtrlSource, const rtl::OUString& rsRowSource ) +{ +// XBindable etc. + uno::Reference< lang::XMultiServiceFactory > xFac; + if ( xModel.is() ) + xFac.set( xModel, uno::UNO_QUERY ); + uno::Reference< form::binding::XBindableValue > xBindable( rPropSet, uno::UNO_QUERY ); + if ( xFac.is() && rsCtrlSource.getLength() && xBindable.is() ) + { + + // OOo address structures + // RefCell - convert from XL + // pretend we converted the imported string address into the + // appropriate address structure + uno::Reference< beans::XPropertySet > xConvertor( xFac->createInstance( C2U( "com.sun.star.table.CellAddressConversion" )), uno::UNO_QUERY ); + table::CellAddress aAddress; + if ( xConvertor.is() ) + { + // we need this service to properly convert XL notation also + // Should be easy to extend + xConvertor->setPropertyValue( C2U( "XL_A1_Representation" ), uno::makeAny( rsCtrlSource ) ); + xConvertor->getPropertyValue( C2U( "Address" ) ) >>= aAddress; + } + + beans::NamedValue aArg1; + aArg1.Name = C2U("BoundCell"); + aArg1.Value <<= aAddress; + + uno::Sequence< uno::Any > aArgs(1); + aArgs[ 0 ] <<= aArg1; + + uno::Reference< form::binding::XValueBinding > xBinding( xFac->createInstanceWithArguments( C2U("com.sun.star.table.CellValueBinding" ), aArgs ), uno::UNO_QUERY ); + xBindable->setValueBinding( xBinding ); + } + uno::Reference< form::binding::XListEntrySink > xListEntrySink( rPropSet, uno::UNO_QUERY ); + if ( xFac.is() && rsRowSource.getLength() && xListEntrySink.is() ) + { + + // OOo address structures + // RefCell - convert from XL + // pretend we converted the imported string address into the + // appropriate address structure + uno::Reference< beans::XPropertySet > xConvertor( xFac->createInstance( C2U( "com.sun.star.table.CellRangeAddressConversion" )), uno::UNO_QUERY ); + table::CellRangeAddress aAddress; + if ( xConvertor.is() ) + { + if ( !lcl_isNamedRange( rsRowSource, xModel, aAddress ) ) + { + // we need this service to properly convert XL notation also + // Should be easy to extend + xConvertor->setPropertyValue( C2U( "XL_A1_Representation" ), uno::makeAny( rsRowSource ) ); + xConvertor->getPropertyValue( C2U( "Address" ) ) >>= aAddress; + } + } + + beans::NamedValue aArg1; + aArg1.Name = C2U("CellRange"); + aArg1.Value <<= aAddress; + + uno::Sequence< uno::Any > aArgs(1); + aArgs[ 0 ] <<= aArg1; + + uno::Reference< form::binding::XListEntrySource > xSource( xFac->createInstanceWithArguments( C2U("com.sun.star.table.CellRangeListSource" ), aArgs ), uno::UNO_QUERY ); + xListEntrySink->setListEntrySource( xSource ); + } +} sal_Bool OCX_OptionButton::Import(com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet> &rPropSet) @@ -1681,12 +1693,51 @@ sal_Bool OCX_OptionButton::Import(com::sun::star::uno::Reference< aTmp <<= ImportSpecEffect( nSpecialEffect ); rPropSet->setPropertyValue( WW8_ASCII2STR("VisualEffect"), aTmp); - if (pValue && !bSetInDialog) + if (pValue) { INT16 nTmp = pValue[0]-0x30; aTmp <<= nTmp; - rPropSet->setPropertyValue( WW8_ASCII2STR("DefaultState"), aTmp); + if (!bSetInDialog) + rPropSet->setPropertyValue( WW8_ASCII2STR("DefaultState"), aTmp); + else + { + // dialog ( but we might be using the form model ) + if ( rPropSet->getPropertySetInfo()->hasPropertyByName( WW8_ASCII2STR("DefaultState") ) ) + rPropSet->setPropertyValue( WW8_ASCII2STR("DefaultState"), aTmp); + else + rPropSet->setPropertyValue( WW8_ASCII2STR("State"), aTmp); + } } + // If this is a dialog control then we need to set a groupname *always* + rtl::OUString sGroupName = lclCreateOUString( pGroupName, nGroupNameLen ); + if ( GetInDialog() ) // Userform/Dialog + { + // By default groupnames are not set in Excel, it's not unusual to have + // a number of groups of radiobuttons located inside frame ( or other container + // controls ) where there is *no* specific groupname set for the radiobuttons. + // But... there is implicit grouping for radio buttons in seperate containers + // e.g. radio buttons in a frame are by default in the same group. + // Unfortunately in openoffice there are no containers below the dialog itself :-( + // To ensure correct grouping for imported radiobuttons either with no groupname + // or identical groupnames that are in separate containers we *must* ensure + // that a suitable groupname is applied. + // Because controlNames are unique even across different containers we can use the + // controls container (e.g. parent) name as a prefix for a group name + rtl::OUString sParentName = msParentName; + sGroupName = sParentName.concat( C2U( ":" ) ).concat( sGroupName ); + } + if ( sGroupName.getLength() == 0 ) + sGroupName = rtl::OUString::createFromAscii("DefaultGroup"); + OSL_TRACE("RadioButton %s has groupname %s", + rtl::OUStringToOString( sName, RTL_TEXTENCODING_UTF8 ).getStr(), rtl::OUStringToOString( sGroupName, RTL_TEXTENCODING_UTF8 ).getStr() ); + try + { + aTmp <<= sGroupName; + rPropSet->setPropertyValue( WW8_ASCII2STR("GroupName"), aTmp); + } + catch( uno::Exception& ) + { + } if (pCaption) { @@ -1698,6 +1749,14 @@ sal_Bool OCX_OptionButton::Import(com::sun::star::uno::Reference< aTmp <<= ::com::sun::star::style::VerticalAlignment_MIDDLE; rPropSet->setPropertyValue( WW8_ASCII2STR("VerticalAlign"), aTmp ); + uno::Reference< frame::XModel > xModel ( pDocSh ? pDocSh->GetModel() : NULL ); + lcl_ApplyListSourceAndBindableStuff( xModel, rPropSet, msCtrlSource, msRowSource ); + if ( sImageUrl.getLength() ) + { + aTmp <<= sImageUrl; + rPropSet->setPropertyValue( WW8_ASCII2STR("ImageURL"), aTmp); + } + aFontData.Import(rPropSet); return sal_True; } @@ -2322,8 +2381,9 @@ sal_Bool OCX_ToggleButton::Import(com::sun::star::uno::Reference< if (pValue) { INT16 nTmp=pValue[0]-0x30; - aTmp <<= nTmp == 1; - rPropSet->setPropertyValue( WW8_ASCII2STR("DefaultState"), aTmp); + //aTmp <<= nTmp == 1; + aTmp <<= nTmp; + rPropSet->setPropertyValue( WW8_ASCII2STR("State"), aTmp); } if (pCaption) @@ -2333,6 +2393,12 @@ sal_Bool OCX_ToggleButton::Import(com::sun::star::uno::Reference< } aFontData.Import(rPropSet); + + if ( sImageUrl.getLength() ) + { + aTmp <<= sImageUrl; + rPropSet->setPropertyValue( WW8_ASCII2STR("ImageURL"), aTmp); + } return sal_True; } @@ -2588,6 +2654,8 @@ sal_Bool OCX_ComboBox::Import(com::sun::star::uno::Reference< rPropSet->setPropertyValue( WW8_ASCII2STR("MaxTextLen"), aTmp); aFontData.Import(rPropSet); + uno::Reference< frame::XModel > xModel ( pDocSh ? pDocSh->GetModel() : NULL ); + lcl_ApplyListSourceAndBindableStuff( xModel, rPropSet, msCtrlSource, msRowSource ); return sal_True; } @@ -2807,7 +2875,8 @@ sal_Bool OCX_ListBox::Import(com::sun::star::uno::Reference< aTmp <<= ImportColor( nBorderColor ); rPropSet->setPropertyValue( WW8_ASCII2STR("BorderColor"), aTmp); - + uno::Reference< frame::XModel > xModel ( pDocSh ? pDocSh->GetModel() : NULL ); + lcl_ApplyListSourceAndBindableStuff( xModel, rPropSet, msCtrlSource, msRowSource ); aFontData.Import(rPropSet); return sal_True; } @@ -3185,8 +3254,15 @@ sal_Bool OCX_ModernControl::Read(SvStorageStream *pS) { pS->Read(pPictureHeader,20); *pS >> nPictureLen; - pPicture = new sal_uInt8[nPictureLen]; - pS->Read(pPicture,nPictureLen); + long imagePos = pS->Tell(); + mxGrfObj = lcl_readGraphicObject( pS ); + if( mxGrfObj.is() ) + { + sImageUrl = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( GRAPHOBJ_URLPREFIX ) ); + sImageUrl = sImageUrl + mxGrfObj->getUniqueID(); + } + // make sure the stream position should be pointing after the image + pS->Seek( imagePos + nPictureLen ); } return sal_True; @@ -3276,8 +3352,15 @@ sal_Bool OCX_CommandButton::Read(SvStorageStream *pS) { pS->Read(pPictureHeader,20); *pS >> nPictureLen; - pPicture = new sal_uInt8[nPictureLen]; - pS->Read(pPicture,nPictureLen); + long imagePos = pS->Tell(); + mxGrfObj = lcl_readGraphicObject( pS ); + if( mxGrfObj.is() ) + { + sImageUrl = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( GRAPHOBJ_URLPREFIX ) ); + sImageUrl = sImageUrl + mxGrfObj->getUniqueID(); + } + // make sure the stream position should be pointing after the image + pS->Seek( imagePos + nPictureLen ); } return sal_True; @@ -3398,7 +3481,7 @@ OCX_ContainerControl::OCX_ContainerControl( SotStorageRef& parent, const ::rtl::OUString& sN, const uno::Reference< container::XNameContainer > &rParent, OCX_Control* pParent ) : - OCX_Control(sN, pParent), rbGroupMgr( sName ), mxParent(rParent), nNoRecords(0), nTotalLen(0), containerType( STDCONTAINER ) + OCX_Control(sN, pParent), mxParent(rParent), nNoRecords(0), nTotalLen(0), containerType( STDCONTAINER ) { mContainerStorage = parent->OpenSotStorage(storageName, @@ -3461,9 +3544,18 @@ OUString OCX_ContainerControl::createSubStreamName( const sal_uInt32& subStorage return buf.makeStringAndClear(); } -bool OCX_ContainerControl::createFromContainerRecord( const ContainerRecord& record, OCX_Control*& pControl ) + +bool OCX_ContainerControl::createFromContainerRecord( ContainerRecord& record, OCX_Control*& pControl ) { pControl = NULL; + if ( record.nTypeIdent & 0x8000 ) + { + std::hash_map<sal_uInt16, sal_uInt16>::iterator it = mActiveXIDMap.find( record.nTypeIdent ); + if ( it == mActiveXIDMap.end() ) + return false; + // replace the generated id with our hardcoded one + record.nTypeIdent = it->second; + } switch ( record.nTypeIdent) { case CMDBUTTON: @@ -3571,8 +3663,7 @@ void OCX_ContainerControl::ProcessControl(OCX_Control* pControl,SvStorageStream* SotStorageStreamRef oStream = mContainedControlsStream; // can insert into OO Dialog (e.g is this a supported dialog control)?? - if ( rec.nTypeIdent == SPINBUTTON || - rec.nTypeIdent == TABSTRIP) + if ( rec.nTypeIdent == TABSTRIP ) { // skip the record in the stream, discard the control oStream->SeekRel( rec.nSubStreamLen ); @@ -3582,15 +3673,27 @@ void OCX_ContainerControl::ProcessControl(OCX_Control* pControl,SvStorageStream* { // A container control needs to read the f stream in // the folder ( substorage ) associated with this control - if ( rec.nTypeIdent == FRAME || - rec.nTypeIdent == MULTIPAGE|| - rec.nTypeIdent == PAGE ) + switch ( rec.nTypeIdent ) { - OCX_ContainerControl* pContainer = - static_cast< OCX_ContainerControl* >( pControl ); - oStream = pContainer->getContainerStream(); + case FRAME: + case MULTIPAGE: + case PAGE: + { + OCX_ContainerControl* pContainer = + static_cast< OCX_ContainerControl* >( pControl ); + oStream = pContainer->getContainerStream(); + break; + } + case LISTBOX: + case OPTIONBUTTON: + case COMBOBOX: + case SPINBUTTON: + case SCROLLBAR: + { + pControl->msCtrlSource = rec.sCtrlSource; + pControl->msRowSource = rec.sRowSource; + } } - pControl->sName = rec.cName; pControl->msToolTip = rec.controlTip; // Position of controls is relative to the container @@ -3610,6 +3713,7 @@ void OCX_ContainerControl::ProcessControl(OCX_Control* pControl,SvStorageStream* // applied to all containees pControl->mnStep = mnStep; } + pControl->msParentName = sName; // #117490# DR: container records provide size of substream, use it here... @@ -3620,17 +3724,7 @@ void OCX_ContainerControl::ProcessControl(OCX_Control* pControl,SvStorageStream* // set stream to position behind substream of this control oStream->Seek( nStrmPos + rec.nSubStreamLen ); - //need to fake grouping behaviour for radio ( option ) buttons - if ( rec.nTypeIdent == OPTIONBUTTON ) - { - OCX_OptionButton* pRButton = - static_cast< OCX_OptionButton*>(pControl); - rbGroupMgr.addRadioButton( pRButton ); - } - else - { - mpControls.push_back( pControl ); - } + mpControls.push_back( pControl ); } } @@ -3653,7 +3747,6 @@ sal_Bool OCX_ContainerControl::Read(SvStorageStream *pS) // this ensures that the default tab index created by Star/Open office // reflects the "flattened" ms tab order. ::std::sort( mpControls.begin(), mpControls.end(), SortOrderByTabPos() ); - mpControls = rbGroupMgr.insertGroupsIntoControlList( mpControls ); return true; } @@ -3671,7 +3764,8 @@ OCX_MultiPage::OCX_MultiPage( SotStorageRef& parent, nScrollWidth(0), nScrollHeight(0), nIconLen(0), pIcon(0), nPictureLen(0), pPicture(0) { - msDialogType = C2U("NotSupported"); + //msDialogType = C2U("NotSupported"); + msDialogType = C2U("com.sun.star.awt.UnoMultiPageModel"); mnForeColor = 0x80000012L, mnBackColor = 0x8000000FL; bSetInDialog = true;// UserForm control only @@ -3735,7 +3829,6 @@ sal_Bool OCX_MultiPage::Read(SvStorageStream *pS) sal_Bool OCX_MultiPage::Import(com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet> &rPropSet) { - // Calls import on contained controls OCX_ContainerControl::Import( rPropSet ); return sal_True; } @@ -3756,6 +3849,43 @@ sal_Bool OCX_MultiPage::Import(com::sun::star::uno::Reference< if ( xPropSet.is() ) { + uno::Reference<lang::XMultiServiceFactory> + xFactory(rDialog, uno::UNO_QUERY); + OSL_TRACE("** MultiPage creating control %s", rtl::OUStringToOString( msDialogType, RTL_TEXTENCODING_UTF8 ).getStr() ); + uno::Reference<uno::XInterface> xCreate = xFactory->createInstance(msDialogType); + if (!xCreate.is()) + return sal_False; + + uno::Reference<awt::XControlModel> xModel(xCreate, uno::UNO_QUERY); + if (!xModel.is()) + return sal_False; + + try + { + // we should just call MultiPage::Import( XPropertySet ) + OSL_TRACE("********* MULTIPAGE cName %s", rtl::OUStringToOString( sName, RTL_TEXTENCODING_UTF8 ).getStr() ); + uno::Any aTmp(&sName,getCppuType((OUString *)0)); + uno::Reference<beans::XPropertySet> xPrps(xModel, uno::UNO_QUERY); + xPrps->setPropertyValue( WW8_ASCII2STR("Name"), aTmp ); + aTmp = uno::makeAny( mnCurrentPageStep ); + xPrps->setPropertyValue( WW8_ASCII2STR("ProgressValueMax"), aTmp ); + // default current page to 0 ( #FIXME, we need to read this value ) + aTmp = uno::makeAny( sal_Int32(0) ); + xPrps->setPropertyValue( WW8_ASCII2STR("ProgressValue"), aTmp ); + OSL_TRACE("********* MULTIPAGE vomitted out properties"); + + // Calls import on contained controls + rDialog->insertByName(sName, uno::makeAny(xModel)); + OSL_TRACE("*** inserted ***"); + } + catch( uno::Exception& ) + { + DBG_ERRORFILE( + ByteString( "OCX_Control::Import - cannot insert control \"" ). + Append( ByteString( sName, RTL_TEXTENCODING_UTF8 ) ). + Append( '"' ).GetBuffer() ); + } + // Calls import on contained pages return OCX_ContainerControl::Import( xPropSet ); } @@ -4042,8 +4172,7 @@ OCX_UserForm::OCX_UserForm( SotStorageRef& parent, nKeepScrollBarsVisible(3), nCycle(0), nBorderStyle(0), nSpecialEffect(0), nPicture(0), nPictureAlignment(2), nPictureSizeMode(0), bPictureTiling(FALSE), nAccelerator(0), nIcon(0), pCaption(0), - nScrollWidth(0), nScrollHeight(0), nScrollLeft(0), nScrollTop(0), nIconLen(0), pIcon(0), nPictureLen(0), - pPicture(0) + nScrollWidth(0), nScrollHeight(0), nScrollLeft(0), nScrollTop(0), nIconLen(0), pIcon(0), nPictureLen(0) { mnForeColor = 0x80000012; mnBackColor = 0x8000000F; @@ -4173,16 +4302,7 @@ sal_Bool OCX_UserForm::Read(SvStorageStream *pS) pS->Read(pIcon,nIconLen); } - if (nPicture) - { - pS->Read(pPictureHeader,20); - *pS >> nPictureLen; - pPicture = new sal_uInt8[nPictureLen]; - pS->Read(pPicture,nPictureLen); - } - ReadAlign( pS, pS->Tell() - nStart, 4); - if (pBlockFlags[2] & 0x10) { //Font Stuff.. @@ -4191,6 +4311,21 @@ sal_Bool OCX_UserForm::Read(SvStorageStream *pS) *pS >> nFontLen; pS->SeekRel(nFontLen); } + if (nPicture) + { + pS->Read(pPictureHeader,20); + *pS >> nPictureLen; + long imagePos = pS->Tell(); + // great embedded object + mxGrfObj = lcl_readGraphicObject( pS ); + if( mxGrfObj.is() ) + { + sImageUrl = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( GRAPHOBJ_URLPREFIX ) ); + sImageUrl = sImageUrl + mxGrfObj->getUniqueID(); + } + // make sure the stream position should be pointing after the image. + pS->Seek( imagePos + nPictureLen ); + } sal_Int16 numTrailingRecs = 0; *pS >> numTrailingRecs; @@ -4199,10 +4334,14 @@ sal_Bool OCX_UserForm::Read(SvStorageStream *pS) // ( unknown what these trailing records are for) if ( numTrailingRecs ) { - for ( ; numTrailingRecs ; --numTrailingRecs ) + for ( sal_Int16 i = 0 ; numTrailingRecs ; --numTrailingRecs, ++i ) { - OCX_Control skip(C2S("dummy")) ; - skip.Read( pS ); + sal_uInt16 nTypeID = 0; + if ( lcl_handleActiveXControl( pS, nTypeID ) ) + { + if ( nTypeID & 0x8000 ) // valid ActiveXID + mActiveXIDMap[ ( i | 0x8000 ) ] = nTypeID; + } } } return OCX_ContainerControl::Read( pS ); @@ -4213,6 +4352,8 @@ sal_Bool OCX_UserForm::Import( { uno::Reference<beans::XPropertySet> xDialogPropSet(mxParent, uno::UNO_QUERY); + if ( !xDialogPropSet.is() ) + return sal_False; uno::Any aTmp(&sName,getCppuType((OUString *)0)); xDialogPropSet->setPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("Name")), aTmp); @@ -4220,22 +4361,55 @@ sal_Bool OCX_UserForm::Import( OUString(RTL_CONSTASCII_USTRINGPARAM("Title")), aTmp); aTmp <<= ImportColor(mnBackColor); xDialogPropSet->setPropertyValue( WW8_ASCII2STR("BackgroundColor"), aTmp); + sal_Bool bVBA = sal_False; + // Ok we are importing xls but maybe we aren't in VBA mode + // if we are not in VBA mode then we should import sizes etc. ( as before ) + try + { + xDialogPropSet->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("VBAForm") ) ) >>= bVBA; + } + catch( uno::Exception& e ) + { + } + if ( !bVBA ) + { + aTmp <<= sal_Int32((nWidth * 2) / 100); + xDialogPropSet->setPropertyValue(WW8_ASCII2STR("Width"), aTmp); + aTmp <<= sal_Int32((nHeight * 2) / 100); + xDialogPropSet->setPropertyValue(WW8_ASCII2STR("Height"), aTmp); + } + else + { + aTmp <<= sal_Int32( nWidth + 160 ); // 100thmm + xDialogPropSet->setPropertyValue(WW8_ASCII2STR("Width"), aTmp); + aTmp <<= sal_Int32(nHeight + 662 - 714); //100th mm + xDialogPropSet->setPropertyValue(WW8_ASCII2STR("Height"), aTmp); + } - aTmp <<= sal_Int32((nWidth * 2) / 100); - xDialogPropSet->setPropertyValue(WW8_ASCII2STR("Width"), aTmp); - aTmp <<= sal_Int32((nHeight * 2) / 100); - xDialogPropSet->setPropertyValue(WW8_ASCII2STR("Height"), aTmp); uno::Reference<beans::XPropertySet> xPropSet( mxParent, uno::UNO_QUERY ); OCX_ContainerControl::Import( xPropSet ); uno::Reference<io::XInputStreamProvider> xSource = - xmlscript::exportDialogModel(mxParent, mxCtx); + xmlscript::exportDialogModel(mxParent, mxCtx, pDocSh->GetModel() ); uno::Any aSourceAny(uno::makeAny(xSource)); if (rLib->hasByName(sName)) rLib->replaceByName(sName, aSourceAny); else rLib->insertByName(sName, aSourceAny); + + if ( sImageUrl.getLength() ) + { + aTmp <<= sImageUrl; + try + { + xDialogPropSet->setPropertyValue( WW8_ASCII2STR("ImageURL"), aTmp); + } + catch( uno::Exception& ) + { + OSL_TRACE("OCX_UserForm::Import, Image fails to import"); + } + } return sal_True; } @@ -4761,11 +4935,14 @@ sal_Bool OCX_CheckBox::Import(com::sun::star::uno::Reference< aTmp <<= ImportSpecEffect( nSpecialEffect ); rPropSet->setPropertyValue( WW8_ASCII2STR("VisualEffect"), aTmp); - if (pValue && !bSetInDialog) + if (pValue) { INT16 nTmp=pValue[0]-0x30; aTmp <<= nTmp; - rPropSet->setPropertyValue( WW8_ASCII2STR("DefaultState"), aTmp); + if ( !bSetInDialog ) + rPropSet->setPropertyValue( WW8_ASCII2STR("DefaultState"), aTmp); + else + rPropSet->setPropertyValue( WW8_ASCII2STR("State"), aTmp); } if (pCaption) @@ -5272,12 +5449,6 @@ sal_Bool OCX_TabStrip::ReadFontData(SotStorageStream *pS) sal_Bool OCX_Image::Read(SotStorageStream *pS) { - if ( !bSetInDialog ) - { - // preserve the present behavior at the moment. - // only import image control for UserForms - return sal_False; - } ULONG nStart = pS->Tell(); *pS >> nIdentifier; DBG_ASSERT(nStandardId==nIdentifier, @@ -5368,16 +5539,14 @@ sal_Bool OCX_Image::Read(SotStorageStream *pS) long imagePos = pS->Tell(); - pS->Seek( imagePos ); - - sImageUrl = C2U("vnd.sun.star.expand:${$BRAND_BASE_DIR/program/") + C2U( SAL_CONFIGFILE( "bootstrap" ) ) + C2U("::UserInstallation}/user/temp/") + sName; - - sal_uInt8* pImage = new sal_uInt8[ nImageLen ]; - pS->Read(pImage, nImageLen); - bool result = storePictureInFileSystem( sImageUrl, pImage, nImageLen ); - OUString pictName = sImageUrl.copy( sImageUrl.lastIndexOf('/') + 1 ); - result = storePictureInDoc( pDocSh, pictName, pImage, nImageLen ); - delete [] pImage; + mxGrfObj = lcl_readGraphicObject( pS ); + if( mxGrfObj.is() ) + { + sImageUrl = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( GRAPHOBJ_URLPREFIX ) ); + sImageUrl = sImageUrl + mxGrfObj->getUniqueID(); + } + // make sure the stream position should be pointing after the image + pS->Seek( imagePos + nImageLen ); } return sal_True; } @@ -5545,7 +5714,7 @@ OCX_SpinButton::OCX_SpinButton() : mbPropThumb( true ) { msFormType = C2U("com.sun.star.form.component.SpinButton"); - msDialogType = C2U("com.sun.star.awt.UnoControlSpinButtonModel"); + msDialogType = C2U("com.sun.star.form.component.SpinButton"); mnBackColor = 0x8000000F; mnForeColor = 0x80000012; } @@ -5582,8 +5751,8 @@ sal_Bool OCX_SpinButton::Read( SvStorageStream *pS ) if( mnBlockFlags & 0x00000080 ) rStrm >> mnValue; if( mnBlockFlags & 0x00000100 ) rStrm.SeekRel( 4 ); // unknown if( mnBlockFlags & 0x00000200 ) rStrm.SeekRel( 4 ); // unknown - if( mnBlockFlags & 0x00000400 ) rStrm.SeekRel( 4 ); // unknown - if( mnBlockFlags & 0x00000800 ) rStrm >> mnSmallStep; + if( mnBlockFlags & 0x00000400 ) rStrm >> mnSmallStep; + if( mnBlockFlags & 0x00000800 ) rStrm.SeekRel( 4 ); // unknown if( mnBlockFlags & 0x00001000 ) rStrm >> mnPageStep; if( mnBlockFlags & 0x00002000 ) rStrm >> mnOrient; if( mnBlockFlags & 0x00004000 ) @@ -5668,6 +5837,9 @@ sal_Bool OCX_SpinButton::Import(com::sun::star::uno::Reference< aTmp <<= sal_Int16( 0 ); rPropSet->setPropertyValue( WW8_ASCII2STR("Border"), aTmp); + uno::Reference< frame::XModel > xModel ( pDocSh ? pDocSh->GetModel() : NULL ); + lcl_ApplyListSourceAndBindableStuff( xModel, rPropSet, msCtrlSource, msRowSource ); + return sal_True; } @@ -5835,7 +6007,7 @@ OCX_ScrollBar::OCX_ScrollBar() sName = OUString( RTL_CONSTASCII_USTRINGPARAM( "ScrollBar" ) ); mnMax = 32767; msFormType = C2U("com.sun.star.form.component.ScrollBar"); - msDialogType = C2U("com.sun.star.awt.UnoControlScrollBarModel"); + msDialogType = C2U("com.sun.star.form.component.ScrollBar"); } @@ -5901,6 +6073,9 @@ sal_Bool OCX_ScrollBar::Import(com::sun::star::uno::Reference< aTmp <<= sal_Int16( 0 ); rPropSet->setPropertyValue( WW8_ASCII2STR("Border"), aTmp); + uno::Reference< frame::XModel > xModel ( pDocSh ? pDocSh->GetModel() : NULL ); + lcl_ApplyListSourceAndBindableStuff( xModel, rPropSet, msCtrlSource, msRowSource ); + return sal_True; } diff --git a/filter/source/msfilter/msoleexp.cxx b/filter/source/msfilter/msoleexp.cxx index 52214ea443c8..a3fa45784977 100644 --- a/filter/source/msfilter/msoleexp.cxx +++ b/filter/source/msfilter/msoleexp.cxx @@ -220,7 +220,12 @@ void SvxMSExportOLEObjects::ExportOLEObject( svt::EmbeddedObjectRef& rObj, SvSto aSeq[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" ) ); aSeq[1].Value <<= ::rtl::OUString( pExpFilter->GetName() ); uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY ); + try + { xStor->storeToURL( ::rtl::OUString::createFromAscii( "private:stream" ), aSeq ); + } + catch( uno::Exception& ) {} // #TODO really handle exceptions - interactionalhandler etc. ? + SotStorageRef xOLEStor = new SotStorage( pStream, TRUE ); xOLEStor->CopyTo( &rDestStg ); rDestStg.Commit(); diff --git a/filter/source/msfilter/msvbasic.cxx b/filter/source/msfilter/msvbasic.cxx index fa954d1177b2..16d57db30175 100644 --- a/filter/source/msfilter/msvbasic.cxx +++ b/filter/source/msfilter/msvbasic.cxx @@ -38,11 +38,804 @@ #include <osl/endian.h> #include <rtl/tencinfo.h> //rtl_getTextEncodingFromWindowsCodePage #include "msvbasic.hxx" +#include <memory> +#include <rtl/ustrbuf.hxx> +#include <boost/shared_ptr.hpp> +#include <boost/scoped_array.hpp> +#include <boost/shared_array.hpp> +#include <svtools/filterutils.hxx> #include <com/sun/star/script/ModuleType.hpp> +#include <fstream> using namespace ::com::sun::star::script; +namespace MSLZSS { + +static unsigned int getShift( sal_uInt32 nPos ) +{ + if (nPos <= 0x80) { + if (nPos <= 0x20) + return (nPos <= 0x10) ? 12 : 11; + else + return (nPos <= 0x40) ? 10 : 9; + } else { + if (nPos <= 0x200) + return (nPos <= 0x100) ? 8 : 7; + else if (nPos <= 0x800) + return (nPos <= 0x400) ? 6 : 5; + else + return 4; + } +} + +SvMemoryStream *decompressAsStream( SvStream *pStream, sal_uInt32 nOffset, sal_uInt32 *pCompressedLength = NULL, sal_uInt32 *pLength = NULL ) +{ + SvMemoryStream *pResult; + const sal_Int32 nWINDOWLEN = 4096; + pResult = new SvMemoryStream(); + + sal_uInt8 nLeadbyte; + unsigned int nPos = 0; + int nLen, nDistance, nShift, nClean=1; + sal_uInt8 aHistory[ nWINDOWLEN ]; + + pStream->Seek( nOffset + 3 ); + + while( pStream->Read( &nLeadbyte, 1 ) ) + { + for(int nMask=0x01; nMask < 0x100; nMask = nMask<<1) + { + // we see if the leadbyte has flagged this location as a dataunit + // which is actually a token which must be looked up in the history + if( nLeadbyte & nMask ) + { + sal_uInt16 nToken; + + *pStream >> nToken; + + if (nClean == 0) + nClean=1; + + //For some reason the division of the token into the length + //field of the data to be inserted, and the distance back into + //the history differs depending on how full the history is + nShift = getShift( nPos % nWINDOWLEN ); + + nLen = (nToken & ((1<<nShift) - 1)) + 3; + nDistance = nToken >> nShift; + + //read the len of data from the history, wrapping around the + //nWINDOWLEN boundary if necessary data read from the history + //is also copied into the recent part of the history as well. + for (int i = 0; i < nLen; i++) + { + unsigned char c; + c = aHistory[(nPos-nDistance-1) % nWINDOWLEN]; + aHistory[nPos % nWINDOWLEN] = c; + nPos++; + } + } + else + { + // special boundary case code, not guarantueed to be correct + // seems to work though, there is something wrong with the + // compression scheme (or maybe a feature) where when the data + // ends on a nWINDOWLEN boundary and the excess bytes in the 8 + // dataunit list are discarded, and not interpreted as tokens + // or normal data. + if ((nPos != 0) && ((nPos % nWINDOWLEN) == 0) && (nClean)) + { + pStream->SeekRel(2); + nClean=0; + pResult->Write( aHistory, nWINDOWLEN ); + break; + } + //This is the normal case for when the data unit is not a + //token to be looked up, but instead some normal data which + //can be output, and placed in the history. + if (pStream->Read(&aHistory[nPos % nWINDOWLEN],1)) + nPos++; + + if (nClean == 0) + nClean=1; + } + } + } + if (nPos % nWINDOWLEN) + pResult->Write( aHistory, nPos % nWINDOWLEN ); + pResult->Flush(); + + if( pCompressedLength ) + *pCompressedLength = nPos; + + if( pLength ) + *pLength = pResult->Tell(); + + pResult->Seek( 0 ); + + return pResult; +} + +} //MSZSS + +// also _VBA_PROJECT_VDPI can be used to create a usable +// ( and much smaller ) "_VBA_PROJECT" stream + +// _VBA_PROJECT Stream Version Dependant Project Information +// _VBA_PROJECT Stream Version Dependant Project Information + +class _VBA_PROJECT_VDPI +{ +public: +sal_Int16 Reserved1; +sal_Int16 Version; +sal_Int8 Reserved2; +sal_Int16 Reserved3; +boost::scoped_array< sal_uInt8 > PerformanceCache; +sal_Int32 PerformanceCacheSize; +_VBA_PROJECT_VDPI(): Reserved1( 0x61CC), Version( 0xFFFF ), Reserved2(0x0), Reserved3(0x0), PerformanceCacheSize(0) {} +~_VBA_PROJECT_VDPI() +{ + PerformanceCacheSize = 0; +} +void read(){} +void write( SvStream* pStream ) +{ + *pStream << Reserved1 << Version << Reserved2 << Reserved3; + if ( PerformanceCacheSize ) + { + PerformanceCache.reset( new sal_uInt8[ PerformanceCacheSize ] ); + pStream->Read( PerformanceCache.get(), PerformanceCacheSize ); + } +} +}; + +class ProjectSysKindRecord +{ +public: +sal_Int16 Id; +sal_Int32 Size; +sal_Int32 SysKind; +ProjectSysKindRecord(): Id(0x1), Size(0x4), SysKind( 0x1 ) {} +void read( SvStream* pStream ) +{ + *pStream >> Id >> Size >> SysKind; +} +}; + +class ProjectLcidRecord +{ +public: +sal_Int16 Id; +sal_Int32 Size; +sal_Int32 Lcid; + +ProjectLcidRecord() : Id( 0x2 ), Size( 0x4 ), Lcid( 0x409 ) {} +void read( SvStream* pStream ) +{ + OSL_TRACE("ProjectLcidRecord [0x%x]", pStream->Tell() ); + *pStream >> Id >> Size >> Lcid; +} +}; + +class ProjectLcidInvokeRecord +{ +sal_Int16 Id; +sal_Int32 Size; +sal_Int32 LcidInvoke; +public: +ProjectLcidInvokeRecord() : Id( 0x14 ), Size( 0x4 ), LcidInvoke( 0x409 ) {} +void read( SvStream* pStream ) +{ + OSL_TRACE("ProjectLcidInvokeRecord [0x%x]", pStream->Tell() ); + *pStream >> Id >> Size >> LcidInvoke; +} +}; + +class ProjectCodePageRecord +{ +sal_Int16 Id; +sal_Int32 Size; +sal_Int16 CodePage; +public: +// #FIXME get a better default for the CodePage +ProjectCodePageRecord() : Id( 0x03 ), Size( 0x2 ), CodePage( 0x0 ) {} +void read( SvStream* pStream ) +{ + OSL_TRACE("ProjectCodePageRecord [0x%x]", pStream->Tell() ); + *pStream >> Id >> Size >> CodePage; +} +}; +class ProjectNameRecord +{ +public: +sal_Int16 Id; +sal_Int32 SizeOfProjectName; +rtl::OUString ProjectName; +ProjectNameRecord() : Id( 0x04 ), SizeOfProjectName( 0x0 ){} +~ProjectNameRecord() +{ +} +void read( SvStream* pStream ) +{ + OSL_TRACE("ProjectNameRecord [0x%x]", pStream->Tell() ); + *pStream >> Id >> SizeOfProjectName; + + if ( SizeOfProjectName ) + { + boost::scoped_array< sal_uInt8 > pProjectName( new sal_uInt8[ SizeOfProjectName ] ); + OSL_TRACE("ProjectNameRecord about to read name from [0x%x], size %d", pStream->Tell(), SizeOfProjectName ); + pStream->Read( pProjectName.get(), SizeOfProjectName ); + ProjectName = svt::BinFilterUtils::CreateOUStringFromStringArray( reinterpret_cast< const char* >( pProjectName.get() ), SizeOfProjectName ); + } +} +}; + +class ProjectDocStringRecord +{ +public: +sal_Int16 Id; +sal_Int32 SizeOfDocString; +sal_Int16 Reserved; +sal_Int32 SizeOfDocStringUnicode; +rtl::OUString DocString; +rtl::OUString DocStringUnicode; + +ProjectDocStringRecord() : Id( 0x5 ), SizeOfDocString( 0x0 ), Reserved( 0x0 ), SizeOfDocStringUnicode( 0 ){} + +~ProjectDocStringRecord() +{ +} +void read( SvStream* pStream ) +{ + OSL_TRACE("ProjectDocStringRecord [0x%x]", pStream->Tell() ); + *pStream >> Id >> SizeOfDocString; + + + boost::scoped_array< sal_uInt8 > pDocString( new sal_uInt8[ SizeOfDocString ] ); + pStream->Read( pDocString.get(), SizeOfDocString ); + + DocString = svt::BinFilterUtils::CreateOUStringFromStringArray( reinterpret_cast< const char* >( pDocString.get() ), SizeOfDocString ); + + *pStream >> Reserved >> SizeOfDocStringUnicode; + + boost::scoped_array< sal_uInt8 > pDocStringUnicode( new sal_uInt8[ SizeOfDocStringUnicode ] ); + + pStream->Read( pDocStringUnicode.get(), SizeOfDocStringUnicode ); + DocStringUnicode = svt::BinFilterUtils::CreateOUStringFromUniStringArray( reinterpret_cast< const char* >( pDocStringUnicode.get() ), SizeOfDocString ); + +} + +}; + +class ProjectHelpFilePath +{ +public: +sal_Int16 Id; +sal_Int32 SizeOfHelpFile1; +boost::scoped_array< sal_uInt8 > HelpFile1; +sal_Int16 Reserved; +sal_Int32 SizeOfHelpFile2; +boost::scoped_array< sal_uInt8 > HelpFile2; + +ProjectHelpFilePath() : Id( 0x06 ), SizeOfHelpFile1(0), Reserved(0x0), SizeOfHelpFile2(0) {} +~ProjectHelpFilePath() +{ +} + +void read( SvStream* pStream ) +{ + OSL_TRACE("ProjectHelpFilePath [0x%x]", pStream->Tell() ); + *pStream >> Id >> SizeOfHelpFile1; + + HelpFile1.reset( new sal_uInt8[ SizeOfHelpFile1 ] ); + pStream->Read( HelpFile1.get(), SizeOfHelpFile1 ); + + *pStream >> Reserved >> SizeOfHelpFile2; + + HelpFile2.reset( new sal_uInt8[ SizeOfHelpFile2 ] ); + pStream->Read( HelpFile2.get(), SizeOfHelpFile2 ); + +} +}; + +class ProjectHelpContextRecord +{ +public: +sal_Int16 Id; +sal_Int32 Size; +sal_Int32 HelpContext; + +ProjectHelpContextRecord() : Id( 0x7 ), Size( 0x4 ), HelpContext( 0 ) {} +void read( SvStream* pStream ) +{ + + OSL_TRACE("ProjectHelpContextRecord [0x%x]", pStream->Tell() ); + *pStream >> Id >> Size >> HelpContext; +} + +}; + +class ProjectLibFlagsRecord +{ +sal_Int16 Id; +sal_Int32 Size; +sal_Int32 ProjectLibFlags; + +public: +ProjectLibFlagsRecord() : Id( 0x8 ), Size( 0x4 ), ProjectLibFlags( 0x0 ) {} +void read( SvStream* pStream ) +{ + OSL_TRACE("ProjectLibFlagsRecord [0x%x]", pStream->Tell() ); + *pStream >> Id >> Size >> ProjectLibFlags; +} +}; + +class ProjectVersionRecord +{ +public: +sal_Int16 Id; +sal_Int32 Reserved; +sal_Int32 VersionMajor; +sal_Int16 VersionMinor; +ProjectVersionRecord() : Id( 0x9 ), Reserved( 0x4 ), VersionMajor( 0x1 ), VersionMinor( 0 ) {} +void read( SvStream* pStream ) +{ + OSL_TRACE("ProjectVersionRecord [0x%x]", pStream->Tell() ); + *pStream >> Id >> Reserved >> VersionMajor >> VersionMinor; +} +}; + +class ProjectConstantsRecord +{ +sal_Int16 Id; +sal_Int32 SizeOfConstants; +boost::scoped_array< sal_uInt8 > Constants; +sal_Int16 Reserved; +sal_Int32 SizeOfConstantsUnicode; +boost::scoped_array< sal_uInt8 > ConstantsUnicode; +public: +ProjectConstantsRecord() : Id( 0xC ), SizeOfConstants( 0 ), Constants( 0 ), Reserved( 0x3C ), SizeOfConstantsUnicode( 0 ), ConstantsUnicode(0) {} + +~ProjectConstantsRecord() +{ +} + +void read( SvStream* pStream ) +{ + OSL_TRACE("ProjectConstantsRecord [0x%x]", pStream->Tell() ); + *pStream >> Id >> SizeOfConstants; + Constants.reset( new sal_uInt8[ SizeOfConstants ] ); + + pStream->Read( Constants.get(), SizeOfConstants ); + + *pStream >> Reserved; + + *pStream >> SizeOfConstantsUnicode; + + ConstantsUnicode.reset( new sal_uInt8[ SizeOfConstantsUnicode ] ); + pStream->Read( ConstantsUnicode.get(), SizeOfConstantsUnicode ); +} + +}; + +class ReferenceNameRecord +{ +public: +sal_Int16 Id; +sal_Int32 SizeOfName; +rtl::OUString Name; +sal_Int16 Reserved; +sal_Int32 SizeOfNameUnicode; +rtl::OUString NameUnicode; + +ReferenceNameRecord() : Id( 0x16 ), SizeOfName( 0 ), Reserved( 0x3E ), SizeOfNameUnicode( 0 ){} +~ReferenceNameRecord() +{ +} + +void read( SvStream* pStream ) +{ + OSL_TRACE("NameRecord [0x%x]", pStream->Tell() ); + *pStream >> Id >> SizeOfName; + + boost::scoped_array< sal_uInt8 > pName( new sal_uInt8[ SizeOfName ] ); + + pStream->Read( pName.get(), SizeOfName ); + Name = svt::BinFilterUtils::CreateOUStringFromStringArray( reinterpret_cast< const char* >( pName.get() ), SizeOfName ); + + *pStream >> Reserved >> SizeOfNameUnicode; + + boost::scoped_array< sal_uInt8 > pNameUnicode( new sal_uInt8[ SizeOfNameUnicode ] ); + pStream->Read( pNameUnicode.get(), SizeOfNameUnicode ); + NameUnicode = svt::BinFilterUtils::CreateOUStringFromUniStringArray( reinterpret_cast< const char* >( pNameUnicode.get() ), SizeOfName ); +} + +}; + +// Baseclass for ReferenceControlRecord, ReferenceRegisteredRecord, ReferenceProjectRecord +class DirDumper; + +class BaseReferenceRecord +{ +public: +virtual ~BaseReferenceRecord(){} +virtual bool read( SvStream* pStream ) = 0; +virtual void import( VBA_Impl& ){} +}; + + +class ReferenceProjectRecord : public BaseReferenceRecord +{ +public: + sal_uInt16 Id; + sal_uInt32 Size; + sal_uInt32 SizeOfLibidAbsolute; + sal_uInt32 SizeOfLibidRelative; + sal_uInt32 MajorVersion; + sal_uInt16 MinorVersion; + rtl::OUString AbsoluteLibid; + rtl::OUString RelativeLibid; + + virtual bool read( SvStream* pStream ); + virtual void import( VBA_Impl& rDir ); + ReferenceProjectRecord(); + ~ReferenceProjectRecord(); +}; + +ReferenceProjectRecord::ReferenceProjectRecord() : Id( 0x000E ), Size( 0 ), SizeOfLibidAbsolute( 0 ), SizeOfLibidRelative( 0 ), MajorVersion( 0 ), MinorVersion( 0 ) +{ +} + +ReferenceProjectRecord::~ReferenceProjectRecord() +{ +} + +bool ReferenceProjectRecord::read( SvStream* pStream ) +{ + OSL_TRACE("ReferenceProjectRecord [0x%x]", pStream->Tell() ); + *pStream >> Id >> Size >> SizeOfLibidAbsolute; + + boost::scoped_array< sal_uInt8 > pLibidAbsolute( new sal_uInt8[ SizeOfLibidAbsolute ] ); + OSL_TRACE("ReferenceProjectRecord about to read LibidAbsolute at [0x%x]", pStream->Tell() ); + pStream->Read( pLibidAbsolute.get(), SizeOfLibidAbsolute ); + + *pStream >> SizeOfLibidRelative; + + boost::scoped_array< sal_uInt8 > pLibidRelative( new sal_uInt8[ SizeOfLibidRelative ] ); + OSL_TRACE("ReferenceProjectRecord about to read LibidRelative at [0x%x]", pStream->Tell() ); + pStream->Read( pLibidRelative.get(), SizeOfLibidRelative ); + + *pStream >> MajorVersion >> MinorVersion; + + // array size is ORed with SVX_MSOCX_COMPRESSED to force processing of ascii bytes ( and not + // 16 bit unicode ) + // the offset of 3 is needed to skip the ProjectReference "*\" and project kind ( 0x4[1-4] ) info. + + AbsoluteLibid = svt::BinFilterUtils::CreateOUStringFromStringArray( reinterpret_cast< const char* >( pLibidAbsolute.get() + 3 ), (SizeOfLibidAbsolute - 3 ) ); + RelativeLibid = svt::BinFilterUtils::CreateOUStringFromStringArray( reinterpret_cast< const char* >( pLibidRelative.get() + 3 ), ( SizeOfLibidRelative -3 ) ); + + OSL_TRACE("ReferenceProjectRecord - absolute path %s", rtl::OUStringToOString( AbsoluteLibid, RTL_TEXTENCODING_UTF8 ).getStr() ); + OSL_TRACE("ReferenceProjectRecord - relative path %s", rtl::OUStringToOString( RelativeLibid, RTL_TEXTENCODING_UTF8 ).getStr() ); + return true; +} + +void ReferenceProjectRecord::import( VBA_Impl& rDir ) +{ + rDir.AddProjectReference( AbsoluteLibid ); +} + +class ReferenceRegisteredRecord : public BaseReferenceRecord +{ +public: + sal_uInt16 Id; + sal_uInt32 Size; + sal_uInt32 SizeOfLibid; + boost::scoped_array< sal_uInt8> pLibid; + sal_Int32 Reserved1; + sal_Int16 Reserved2; + + ReferenceRegisteredRecord(); + ~ReferenceRegisteredRecord(); + bool read( SvStream* pStream ); +}; + +ReferenceRegisteredRecord::ReferenceRegisteredRecord() : Id( 0x000D ), Size( 0 ), SizeOfLibid( 0 ), Reserved1( 0 ), Reserved2( 0 ) +{ +} + +ReferenceRegisteredRecord::~ReferenceRegisteredRecord() +{ +} + +bool +ReferenceRegisteredRecord::read( SvStream* pStream ) +{ + OSL_TRACE("ReferenceRegisteredRecord [0x%x]", pStream->Tell() ); + *pStream >> Id >> Size >> SizeOfLibid; + if ( SizeOfLibid ) + { + pLibid.reset( new sal_uInt8[ SizeOfLibid] ); + pStream->Read( pLibid.get(), SizeOfLibid ); + } + *pStream >> Reserved1 >> Reserved2; + return true; +} + +class ReferenceOriginalRecord +{ +public: + sal_uInt16 Id; + sal_uInt32 SizeOfLibOriginal; + boost::scoped_array< sal_uInt8 > pLibidOriginal; + + +ReferenceOriginalRecord() : Id( 0x033 ), SizeOfLibOriginal( 0 ) +{ +} + +~ReferenceOriginalRecord() +{ +} + +void read( SvStream* pStream ) +{ + *pStream >> Id >> SizeOfLibOriginal; + if ( SizeOfLibOriginal ) + { + pLibidOriginal.reset( new sal_uInt8[ SizeOfLibOriginal ] ); + pStream->Read( pLibidOriginal.get(), SizeOfLibOriginal ); + } +} + +}; + +class ReferenceControlRecord : public BaseReferenceRecord +{ +public: +std::auto_ptr< ReferenceOriginalRecord > OriginalRecord; +sal_Int16 Id; +sal_uInt32 SizeTwiddled; +sal_uInt32 SizeOfLibidTwiddled; +boost::shared_array< sal_uInt8 > LibidTwiddled; +sal_uInt32 Reserved1; +sal_uInt16 Reserved2; +std::auto_ptr< ReferenceNameRecord > NameRecordExtended;// Optional +sal_uInt16 Reserved3; +sal_uInt32 SizeExtended; +sal_uInt32 SizeOfLibidExtended; +boost::shared_array< sal_uInt8 > LibidExtended; +sal_uInt32 Reserved4; +sal_uInt16 Reserved5; +sal_uInt8 OriginalTypeLib[ 16 ]; +sal_uInt32 Cookie; + +ReferenceControlRecord() : Id( 0x2F ), SizeTwiddled( 0 ), SizeOfLibidTwiddled( 0 ), Reserved1( 0 ), Reserved2( 0 ), Reserved3( 0x30 ), SizeExtended( 0 ), SizeOfLibidExtended( 0 ), Reserved4( 0 ), Reserved5( 0 ), Cookie( 0 ) +{ + for( int i = 0; i < 16; ++i ) + OriginalTypeLib[ i ] = 0; +} + +~ReferenceControlRecord() +{ +} + +bool read( SvStream* pStream ) +{ + OSL_TRACE("ReferenceControlRecord [0x%x]", pStream->Tell() ); + long nPos = pStream->Tell(); + + *pStream >> Id; + pStream->Seek( nPos ); // point before the peeked Id + if ( Id == 0x33 ) // we have an OriginalRecord + { + OriginalRecord.reset( new ReferenceOriginalRecord() ); + OriginalRecord->read( pStream ); + } + *pStream >> Id >> SizeTwiddled >> SizeOfLibidTwiddled; + + if ( SizeOfLibidTwiddled ) + { + LibidTwiddled.reset( new sal_uInt8[ SizeOfLibidTwiddled ] ); + pStream->Read( LibidTwiddled.get(), SizeOfLibidTwiddled ); + } + + *pStream >> Reserved1 >> Reserved2; + + nPos = pStream->Tell(); + // peek at the id for optional NameRecord + sal_Int16 nTmpId; + *pStream >> nTmpId; + if ( nTmpId == 0x30 ) + { + Reserved3 = 0x30; + } + else + { + pStream->Seek( nPos ); + NameRecordExtended.reset( new ReferenceNameRecord() ); + NameRecordExtended->read( pStream ); + *pStream >> Reserved3; + } + *pStream >> SizeExtended >> SizeOfLibidExtended; + + if ( SizeExtended ) + { + LibidExtended.reset( new sal_uInt8[ SizeOfLibidExtended ] ); + pStream->Read( LibidExtended.get(), SizeOfLibidExtended ); + } + + *pStream >> Reserved4; + *pStream >> Reserved5; + + pStream->Read( OriginalTypeLib, sizeof( OriginalTypeLib ) ); + *pStream >> Cookie; + return true; +} + +}; + +class ReferenceRecord : public BaseReferenceRecord +{ +public: +// NameRecord is Optional +std::auto_ptr< ReferenceNameRecord > NameRecord; +std::auto_ptr< BaseReferenceRecord > aReferenceRecord; + +ReferenceRecord(){} +~ReferenceRecord() +{ +} + +// false return would mean failed to read Record e.g. end of array encountered +// Note: this read routine will make sure the stream is pointing to where it was the +// method was called ) + +bool read( SvStream* pStream ) +{ + OSL_TRACE("ReferenceRecord [0x%x]", pStream->Tell() ); + bool bRead = true; + long nStart = pStream->Tell(); + long nPos = nStart; + // Peek at the ID + sal_Int16 Id; + *pStream >> Id; + pStream->Seek( nPos ); // place back before Id + if ( Id == 0x16 ) // Optional NameRecord + { + NameRecord.reset( new ReferenceNameRecord() ); + NameRecord->read( pStream ); + } + else if ( Id == 0x0f ) + { + pStream->Seek( nStart ); + bRead = false; + return bRead; // start of module, terminate read + } + + nPos = pStream->Tell(); // mark position, peek at next Id + *pStream >> Id; + pStream->Seek( nPos ); // place back before Id + + switch( Id ) + { + case 0x0D: + aReferenceRecord.reset( new ReferenceRegisteredRecord() ); + break; + case 0x0E: + aReferenceRecord.reset( new ReferenceProjectRecord() ); + break; + case 0x2F: + case 0x33: + aReferenceRecord.reset( new ReferenceControlRecord() ); + break; + default: + bRead = false; + OSL_TRACE("Big fat error, unknown ID 0x%x", Id); + break; + } + if ( bRead ) + aReferenceRecord->read( pStream ); + return bRead; +} + +void import( VBA_Impl& rVBA ) +{ + if ( aReferenceRecord.get() ) + aReferenceRecord->import( rVBA ); +} + +}; + +class DirDumper +{ +public: +ProjectSysKindRecord mSysKindRec; +ProjectLcidRecord mLcidRec; +ProjectLcidInvokeRecord mLcidInvokeRec; +ProjectCodePageRecord mCodePageRec; +ProjectNameRecord mProjectNameRec; +ProjectDocStringRecord mDocStringRec; +ProjectHelpFilePath mHelpFileRec; +ProjectHelpContextRecord mHelpContextRec; +ProjectLibFlagsRecord mLibFlagsRec; +ProjectVersionRecord mVersionRec; +ProjectConstantsRecord mConstantsRecord; +std::vector< ReferenceRecord* > ReferenceArray; + +DirDumper() {} +~DirDumper() +{ + for ( std::vector< ReferenceRecord* >::iterator it = ReferenceArray.begin(); it != ReferenceArray.end(); ++it ) + delete *it; + +} + +void read( SvStream* pStream ) +{ + sal_Int32 nPos = pStream->Tell(); +#ifdef DEBUG + std::ofstream aDump("dir.dump"); + while ( !pStream->IsEof() ) + { + sal_Int8 aByte; + *pStream >> aByte; + aDump << aByte; + } + aDump.flush(); +#endif + pStream->Seek( nPos ); + readProjectInformation( pStream ); + readProjectReferenceInformation( pStream ); +} + +void readProjectReferenceInformation( SvStream* pStream ) +{ + bool bKeepReading = true; + while( bKeepReading ) + { + ReferenceRecord* pRef = new ReferenceRecord(); + bKeepReading = pRef->read( pStream ); + if ( bKeepReading ) + ReferenceArray.push_back( pRef ); + } +} + +void readProjectInformation( SvStream* pStream ) +{ + mSysKindRec.read( pStream ); + mLcidRec.read( pStream ); + mLcidInvokeRec.read( pStream ); + mCodePageRec.read( pStream ); + mProjectNameRec.read( pStream ); + mDocStringRec.read( pStream ); + mHelpFileRec.read( pStream ); + mHelpContextRec.read( pStream ); + mLibFlagsRec.read( pStream ); + mVersionRec.read( pStream ); + sal_Int32 nPos = pStream->Tell(); + sal_uInt16 nTmp; + *pStream >> nTmp; + if ( nTmp == 0x0C ) + { + pStream->Seek( nPos ); + mConstantsRecord.read( pStream ); + } + OSL_TRACE("After Information pos is 0x%x", pStream->Tell() ); +} + +void import( VBA_Impl& rVBA ) +{ + // get project references + for ( std::vector< ReferenceRecord* >::iterator it = ReferenceArray.begin(); it != ReferenceArray.end(); ++it ) + (*it)->import( rVBA ); + rVBA.SetProjectName( mProjectNameRec.ProjectName ); + +} +}; + + /* A few urls which may in the future be of some use http://www.virusbtn.com/vb2000/Programme/papers/bontchev.pdf @@ -155,7 +948,21 @@ int VBA_Impl::ReadVBAProject(const SvStorageRef &rxVBAStorage) xVBAProject = rxVBAStorage->OpenSotStream( String( RTL_CONSTASCII_USTRINGPARAM( "_VBA_PROJECT" ) ), STREAM_STD_READ | STREAM_NOCREATE ); - + // read Dir stream + SvStorageStreamRef xDir = rxVBAStorage->OpenSotStream( + String( RTL_CONSTASCII_USTRINGPARAM( "dir" ) ), + STREAM_STD_READ | STREAM_NOCREATE ); +// disable read and import of Dir stream bits, e.g. project references and +// project name for 3.1 ( a bit unstable yet ) +#if 1 + // decompress the stream + std::auto_ptr< SvMemoryStream > xCmpDir; + xCmpDir.reset( MSLZSS::decompressAsStream( xDir, 0 ) ); + // try to parse the dir stream + DirDumper dDump; + dDump.read( xCmpDir.get() ); + dDump.import( *this ); +#endif if( !xVBAProject.Is() || SVSTREAM_OK != xVBAProject->GetError() ) { DBG_WARNING("Not able to find vba project, cannot find macros"); @@ -416,6 +1223,7 @@ bool VBA_Impl::Open( const String &rToplevel, const String &rSublevel ) if( !xMacros.Is() || SVSTREAM_OK != xMacros->GetError() ) { DBG_WARNING("No Macros Storage"); + OSL_TRACE("No Macros Storage"); } else { @@ -425,6 +1233,7 @@ bool VBA_Impl::Open( const String &rToplevel, const String &rSublevel ) if( !xVBA.Is() || SVSTREAM_OK != xVBA->GetError() ) { DBG_WARNING("No Visual Basic in Storage"); + OSL_TRACE("No Visual Basic in Storage"); } else { @@ -439,6 +1248,7 @@ bool VBA_Impl::Open( const String &rToplevel, const String &rSublevel ) * ( value ) is either a Class Module, Form Module or a plain VB Module. */ SvStorageStreamRef xProject = xMacros->OpenSotStream( String( RTL_CONSTASCII_USTRINGPARAM( "PROJECT" ) ) ); + SvStorageStream* pStp = xProject; UniString tmp; static const String sThisDoc( RTL_CONSTASCII_USTRINGPARAM( "ThisDocument" ) ); diff --git a/filter/source/msfilter/msvbasic.hxx b/filter/source/msfilter/msvbasic.hxx index 171671e8cd5c..39d35ee68ae6 100644 --- a/filter/source/msfilter/msvbasic.hxx +++ b/filter/source/msfilter/msvbasic.hxx @@ -36,6 +36,8 @@ #include <tools/dynary.hxx> #include <vector> #include <map> +#include <com/sun/star/script/ModuleType.hpp> +using namespace ::com::sun::star::script::ModuleType; /* class VBA: * The VBA class provides a set of methods to handle Visual Basic For @@ -86,8 +88,14 @@ public: // // #117718# member map of module names to types of module ModType GetModuleType( const UniString& rModuleName ); - std::vector<String> maReferences; + rtl::OUString& ProjectName() { return msProjectName; } + void SetProjectName( const rtl::OUString& rPName ) { msProjectName = rPName; } + const std::vector<rtl::OUString>& ProjectReferences() { return maPrjReferences; } + void AddProjectReference( const rtl::OUString& rProject ) { maPrjReferences.push_back( rProject); } + SvStorage* GetStorage() { return xStor; } private: + std::vector<rtl::OUString> maReferences; + std::vector<rtl::OUString> maPrjReferences; struct VBAOffset_Impl { String sName; @@ -113,6 +121,7 @@ private: int ReadVBAProject(const SvStorageRef &rxVBAStorage); int DecompressVBA(int index, SvStorageStreamRef &rxVBAStream); sal_uInt8 ReadPString(SvStorageStreamRef &xVBAProject, bool bIsUnicode); + rtl::OUString msProjectName; }; #endif diff --git a/filter/source/msfilter/svxmsbas.cxx b/filter/source/msfilter/svxmsbas.cxx index 73af7161fcac..ea5c58fb44be 100644 --- a/filter/source/msfilter/svxmsbas.cxx +++ b/filter/source/msfilter/svxmsbas.cxx @@ -66,6 +66,27 @@ using rtl::OUString; static ::rtl::OUString sVBAOption( RTL_CONSTASCII_USTRINGPARAM( "Option VBASupport 1\n" ) ); +void SvxImportMSVBasic::extractAttribute( const String& rAttribute, const String& rModName ) +{ + // format of the attribute we are interested in is + // Attribute VB_Control = "ControlName", intString, MSForms, ControlTypeAsString + // e.g. + // Attribute VB_Control = "CommandButton1, 201, 19, MSForms, CommandButton" + String sControlAttribute( RTL_CONSTASCII_USTRINGPARAM("Attribute VB_Control = \"") ); + if ( rAttribute.Search( sControlAttribute ) != STRING_NOTFOUND ) + { + String sRest = rAttribute.Copy( sControlAttribute.Len() ); + xub_StrLen nPos = 0; + String sCntrlName = sRest.GetToken( 0, ',', nPos ); + + sal_Int32 nCntrlId = sRest.GetToken( 0, ',', nPos).ToInt32(); + OSL_TRACE("In module %s, assiging %d controlname %s", + rtl::OUStringToOString( rModName, RTL_TEXTENCODING_UTF8 ).getStr(), nCntrlId, + rtl::OUStringToOString( sCntrlName, RTL_TEXTENCODING_UTF8 ).getStr() ); + m_ModuleNameToObjIdHash[ rModName ][ nCntrlId ] = sCntrlName; + } +} + int SvxImportMSVBasic::Import( const String& rStorageName, const String &rSubStorageName, BOOL bAsComment, BOOL bStripped ) @@ -73,19 +94,19 @@ int SvxImportMSVBasic::Import( const String& rStorageName, std::vector< String > codeNames; return Import( rStorageName, rSubStorageName, codeNames, bAsComment, bStripped ); } - int SvxImportMSVBasic::Import( const String& rStorageName, const String &rSubStorageName, const std::vector< String >& codeNames, BOOL bAsComment, BOOL bStripped ) { + msProjectName = rtl::OUString(); int nRet = 0; if( bImport && ImportCode_Impl( rStorageName, rSubStorageName, codeNames, bAsComment, bStripped )) nRet |= 1; if (bImport) - ImportForms_Impl(rStorageName, rSubStorageName); + ImportForms_Impl(rStorageName, rSubStorageName, !bAsComment); if( bCopy && CopyStorage_Impl( rStorageName, rSubStorageName )) nRet |= 2; @@ -94,9 +115,44 @@ int SvxImportMSVBasic::Import( const String& rStorageName, } bool SvxImportMSVBasic::ImportForms_Impl(const String& rStorageName, - const String& rSubStorageName) + const String& rSubStorageName, BOOL bVBAMode ) +{ + BOOL bRet = FALSE; + // #FIXME VBA_Impl ( or some other new class ) should handle both userforms + // and code + VBA_Impl aVBA( *xRoot, TRUE ); + // This call is a waste we read the source ( again ) only to get the refereneces + // *AGAIN*, we really need to rewrite all of this + aVBA.Open( rStorageName, rSubStorageName ); + + bRet = ImportForms_Impl( aVBA, rStorageName, rSubStorageName, bVBAMode ); + std::vector<rtl::OUString> sProjectRefs = aVBA.ProjectReferences(); + + for ( std::vector<rtl::OUString>::iterator it = sProjectRefs.begin(); it != sProjectRefs.end(); ++it ) + { + rtl::OUString sFileName = *it; +#ifndef WIN +#ifdef DEBUG + // hacky test code to read referenced projects on linux + sal_Int32 nPos = (*it).lastIndexOf('\\'); + sFileName = (*it).copy( nPos + 1 ); + sFileName = rtl::OUString::createFromAscii("~/Documents/") + sFileName; +#endif +#endif + SotStorageRef rRoot = new SotStorage( sFileName, STREAM_STD_READWRITE, STORAGE_TRANSACTED ); + VBA_Impl refVBA( *rRoot, TRUE ); + refVBA.Open( rStorageName, rSubStorageName ); + // The return from ImportForms doesn't indicate and error ( it could ) + // but also it just means no userforms were imported + if ( ImportForms_Impl( refVBA, rStorageName, rSubStorageName, bVBAMode ) ) + bRet = true; // mark that at least on userform was imported + } + return bRet; +} + +bool SvxImportMSVBasic::ImportForms_Impl( VBA_Impl& rVBA, const String& rStorageName, const String& rSubStorageName, BOOL bVBAMode ) { - SvStorageRef xVBAStg(xRoot->OpenSotStorage(rStorageName, + SvStorageRef xVBAStg(rVBA.GetStorage()->OpenSotStorage(rStorageName, STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYALL)); if (!xVBAStg.Is() || xVBAStg->GetError()) return false; @@ -129,6 +185,10 @@ bool SvxImportMSVBasic::ImportForms_Impl(const String& rStorageName, DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" ); String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); + + if (rVBA.ProjectName().getLength() ) + aLibName = rVBA.ProjectName(); + OSL_TRACE( "userformage lib name %s", rtl::OUStringToOString( aLibName, RTL_TEXTENCODING_UTF8 ).getStr() ); Reference<XNameContainer> xLib; if (xLibContainer.is()) { @@ -178,7 +238,17 @@ bool SvxImportMSVBasic::ImportForms_Impl(const String& rStorageName, xSF->createInstance( OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.UnoControlDialogModel"))), uno::UNO_QUERY); - + // #FIXME HACK - mark the Model with the VBA mode + // In vba mode the imported userform uses 100th mm as units + // or geometry + // In non vba mode MAP_APPFONT is used ( same as normal basic + // dialogs + if ( bVBAMode ) + { + Reference<XPropertySet> xDlgProps(xDialog, UNO_QUERY); + if ( xDlgProps.is() ) + xDlgProps->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("VBAForm") ), uno::makeAny( sal_True ) ); + } OCX_UserForm aForm(xVBAStg, *aIter, *aIter, xDialog, xSF ); aForm.pDocSh = &rDocSh; sal_Bool bOk = aForm.Read(xTypes); @@ -247,8 +317,34 @@ BOOL SvxImportMSVBasic::ImportCode_Impl( const String& rStorageName, { BOOL bRet = FALSE; VBA_Impl aVBA( *xRoot, bAsComment ); + if( aVBA.Open(rStorageName,rSubStorageName) ) { + msProjectName = aVBA.ProjectName(); + + if ( msProjectName.getLength() ) + rDocSh.GetBasicManager()->SetName( msProjectName ); // set name of Project + + bRet = ImportCode_Impl( aVBA, codeNames, bAsComment, bStripped ); + std::vector<rtl::OUString> sProjectRefs = aVBA.ProjectReferences(); + + for ( std::vector<rtl::OUString>::iterator it = sProjectRefs.begin(); it != sProjectRefs.end(); ++it ) + { + rtl::OUString sFileName = *it; + OSL_TRACE("referenced project %s ", rtl::OUStringToOString( sFileName, RTL_TEXTENCODING_UTF8 ).getStr() ); + SotStorageRef rRoot = new SotStorage( sFileName, STREAM_STD_READWRITE, STORAGE_TRANSACTED ); + VBA_Impl refVBA( *rRoot, bAsComment ); + std::vector< String > codeNamesNone; + if( refVBA.Open(rStorageName,rSubStorageName) && ImportCode_Impl( refVBA, codeNamesNone, bAsComment, bStripped ) ) + bRet = TRUE; // mark that some code was imported + } + } + return bRet; +} + +BOOL SvxImportMSVBasic::ImportCode_Impl( VBA_Impl& aVBA, const std::vector< String >& codeNames, BOOL bAsComment, BOOL bStripped ) +{ + BOOL bRet = FALSE; SFX_APP()->EnterBasicCall(); Reference<XLibraryContainer> xLibContainer = rDocSh.GetBasicContainer(); DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" ); @@ -269,6 +365,8 @@ BOOL SvxImportMSVBasic::ImportCode_Impl( const String& rStorageName, UINT16 nStreamCount = aVBA.GetNoStreams(); Reference<XNameContainer> xLib; String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) ); + if ( aVBA.ProjectName().getLength() ) + aLibName = aVBA.ProjectName(); if( xLibContainer.is() && nStreamCount ) { if( !xLibContainer->hasByName( aLibName ) ) @@ -417,7 +515,11 @@ BOOL SvxImportMSVBasic::ImportCode_Impl( const String& rStorageName, if( nEnd == STRING_NOTFOUND ) pStr->Erase(); else + { + String sAttr= pStr->Copy( nBegin, (nEnd-nBegin)+1); + extractAttribute( sAttr, sModule ); pStr->Erase(nBegin, (nEnd-nBegin)+1); + } } } if( aDecompressed.Get(j)->Len() ) @@ -496,7 +598,6 @@ BOOL SvxImportMSVBasic::ImportCode_Impl( const String& rStorageName, bRet = true; } SFX_APP()->LeaveBasicCall(); - } return bRet; } diff --git a/oox/inc/oox/ole/vbacontrol.hxx b/oox/inc/oox/ole/vbacontrol.hxx index c2490b3506bf..bc443108f5bd 100644..100755 --- a/oox/inc/oox/ole/vbacontrol.hxx +++ b/oox/inc/oox/ole/vbacontrol.hxx @@ -29,6 +29,7 @@ #define OOX_OLE_VBACONTROL_HXX #include "oox/ole/axcontrol.hxx" +#include <com/sun/star/frame/XModel.hpp> namespace com { namespace sun { namespace star { namespace container { class XNameContainer; } @@ -192,6 +193,7 @@ public: /** Imports the form and its embedded controls, and inserts the form with all its controls into the passed dialog library. */ void importForm( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& rxDocModel, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& rxDialogLib, StorageBase& rVbaFormStrg, const ::rtl::OUString& rModuleName, diff --git a/oox/source/ole/vbacontrol.cxx b/oox/source/ole/vbacontrol.cxx index 218163b70286..386c1a034641 100644..100755 --- a/oox/source/ole/vbacontrol.cxx +++ b/oox/source/ole/vbacontrol.cxx @@ -58,6 +58,7 @@ using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::UNO_QUERY_THROW; using ::com::sun::star::uno::UNO_SET_THROW; using ::com::sun::star::uno::XComponentContext; +using ::com::sun::star::frame::XModel; namespace oox { namespace ole { @@ -759,7 +760,7 @@ VbaUserForm::VbaUserForm( const Reference< XMultiServiceFactory >& rxGlobalFacto OSL_ENSURE( mxGlobalFactory.is(), "VbaUserForm::VbaUserForm - missing service factory" ); } -void VbaUserForm::importForm( const Reference< XNameContainer >& rxDialogLib, +void VbaUserForm::importForm( const Reference< XModel >& rxDocModel, const Reference< XNameContainer >& rxDialogLib, StorageBase& rVbaFormStrg, const OUString& rModuleName, rtl_TextEncoding eTextEnc ) { OSL_ENSURE( rxDialogLib.is(), "VbaUserForm::importForm - missing dialog library" ); @@ -830,7 +831,7 @@ void VbaUserForm::importForm( const Reference< XNameContainer >& rxDialogLib, // export the dialog to XML and insert it into the dialog library PropertySet aFactoryProps( mxGlobalFactory ); Reference< XComponentContext > xCompContext( aFactoryProps.getAnyProperty( PROP_DefaultContext ), UNO_QUERY_THROW ); - Reference< XInputStreamProvider > xDialogSource( ::xmlscript::exportDialogModel( xDialogNC, xCompContext ), UNO_SET_THROW ); + Reference< XInputStreamProvider > xDialogSource( ::xmlscript::exportDialogModel( xDialogNC, xCompContext, rxDocModel ), UNO_SET_THROW ); OSL_ENSURE( !rxDialogLib->hasByName( aFormName ), "VbaUserForm::importForm - multiple dialogs with equal name" ); ContainerHelper::insertByName( rxDialogLib, aFormName, Any( xDialogSource ) ); } diff --git a/oox/source/ole/vbaproject.cxx b/oox/source/ole/vbaproject.cxx index c7830582d0ef..fad2dba04ffa 100644..100755 --- a/oox/source/ole/vbaproject.cxx +++ b/oox/source/ole/vbaproject.cxx @@ -419,7 +419,7 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap // create and import the form Reference< XNameContainer > xDialogLib( createDialogLibrary(), UNO_SET_THROW ); VbaUserForm aForm( mxGlobalFactory, rGraphicHelper, bDefaultColorBgr ); - aForm.importForm( xDialogLib, *xSubStrg, aModuleName, eTextEnc ); + aForm.importForm( mxDocModel, xDialogLib, *xSubStrg, aModuleName, eTextEnc ); } catch( Exception& ) { |