diff options
author | Noel Power <noel.power@novell.com> | 2010-11-02 15:59:53 +0000 |
---|---|---|
committer | Noel Power <noel.power@novell.com> | 2010-11-02 19:49:48 +0000 |
commit | e274ec121b99173740dd39755232184b0a2dcc23 (patch) | |
tree | 7be90cea076ab0da5f3dda14bd03edb53e4b1643 | |
parent | binfilters: 6926 warnings down, 29191 to go.... (diff) | |
download | core-e274ec121b99173740dd39755232184b0a2dcc23.tar.gz core-e274ec121b99173740dd39755232184b0a2dcc23.zip |
initial import of latest cws container_controls
24 files changed, 2060 insertions, 1757 deletions
diff --git a/filter/inc/filter/msfilter/msocximex.hxx b/filter/inc/filter/msfilter/msocximex.hxx index 7269b1f7f5bb..829c029a469b 100644 --- a/filter/inc/filter/msfilter/msocximex.hxx +++ b/filter/inc/filter/msfilter/msocximex.hxx @@ -294,6 +294,8 @@ public: rtl::OUString msCtrlSource; rtl::OUString msRowSource; SfxObjectShell *pDocSh; + ::rtl::OUString sImageUrl; + com::sun::star::uno::Reference< com::sun::star::graphic::XGraphicObject> mxGrfObj; protected: sal_uInt32 ImportColor(sal_uInt32 nColorCode) const; @@ -416,22 +418,23 @@ public: sal_uInt8 pPictureHeader[20]; sal_uInt32 nPictureLen; - ::rtl::OUString sImageUrl; - com::sun::star::uno::Reference< com::sun::star::graphic::XGraphicObject> mxGrfObj; }; class OCX_TabStrip : public OCX_Control { public: - OCX_TabStrip() : OCX_Control( rtl::OUString::createFromAscii("TabStrip")) {} + OCX_TabStrip() : OCX_Control( rtl::OUString::createFromAscii("TabStrip")), nIdentifier(0), nFixedAreaLen(0), nNumTabs(0), bHasTabs(true) {} + virtual sal_Bool ReadFontData(SotStorageStream *pS); virtual sal_Bool Read(SotStorageStream *pS); + std::vector< rtl::OUString > msItems; sal_uInt16 nIdentifier; sal_uInt16 nFixedAreaLen; sal_uInt8 pBlockFlags[4]; - sal_uInt16 nNumTabs; + sal_Int32 nNumTabs; + bool bHasTabs; }; class OCX_Image : public OCX_Control @@ -465,8 +468,6 @@ public: sal_uInt8 nSpecialEffect; 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 @@ -487,8 +488,7 @@ public: }; struct ContainerRecord { - ContainerRecord():nTop(0), nLeft(0), nSubStorageId(0), nSubStreamLen(0), nTabPos(0), nTypeIdent(0), bVisible( true ) {} - + ContainerRecord():nTop(0), nLeft(0), nSubStorageId(0), nSubStreamLen(0), nTabPos(0), nTypeIdent(0), bVisible( true ), bTabStop( true ) {} ::rtl::OUString cName; ::rtl::OUString controlTip; ::rtl::OUString sCtrlSource; @@ -501,6 +501,7 @@ struct ContainerRecord sal_uInt16 nTabPos; sal_uInt16 nTypeIdent; bool bVisible; + bool bTabStop; }; typedef std::vector<OCX_Control*>::iterator CtrlIterator; @@ -509,44 +510,32 @@ typedef std::vector<OCX_Control*> CtrlList; class OCX_OptionButton; -class OCX_ContainerControl : public OCX_Control +class OCX_ParentControl : public OCX_Control { public: - virtual ~OCX_ContainerControl(); - // sub class will process the control specific information - // e.g frame or userform ( maybe tab, mulipage in the future ) - // Base (this) class will process the container specific information - // e.g. the controls contained by this container - // will - // a) create the controls - // b) read the controls - // c) store these controls in a list for post processing - // e.g. import - // virtual sal_Bool Read(SvStorageStream *pS); - // No Font record virtual sal_Bool ReadFontData(SvStorageStream* /*pS*/) { return sal_True; } using OCX_Control::Import; // to not hide the other two import methods + virtual sal_Bool Import(com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet> &rPropSet); SotStorageStreamRef getContainerStream() { return mContainerStream; } + SotStorageStreamRef getOStream() { return mContainedControlsStream; } virtual void ProcessControl( OCX_Control* pControl, SvStorageStream* pS, ContainerRecord& rec ); - bool createFromContainerRecord( ContainerRecord& record, + bool createFromContainerRecord( const ContainerRecord& record, OCX_Control*& ); SotStorageStreamRef getContainedControlsStream(){ return mContainedControlsStream; } protected: - // This class not meant to be instantiated - // needs to be subclassed - OCX_ContainerControl( SotStorageRef& parent, + OCX_ParentControl( SotStorageRef& parent, const ::rtl::OUString& storageName, const ::rtl::OUString& sN, const com::sun::star::uno::Reference< - com::sun::star::container::XNameContainer > &rParent, + com::sun::star::container::XNameContainer > &rDialog, OCX_Control* pParent = NULL ); - rtl::OUString createSubStreamName( const sal_uInt32& subStorageID ); + ~OCX_ParentControl(); com::sun::star::uno::Reference< com::sun::star::container::XNameContainer > mxParent; @@ -555,84 +544,56 @@ protected: SotStorageRef mContainerStorage; SotStorageStreamRef mContainerStream; SotStorageStreamRef mContainedControlsStream; - sal_uInt32 nNoRecords; - sal_uInt32 nTotalLen; - sal_uInt32 containerType; - -private: - OCX_ContainerControl(); // not implemented - OCX_ContainerControl(const OCX_ContainerControl&); // not implemented -}; - - -class OCX_MultiPage : public OCX_ContainerControl -{ -public: - OCX_MultiPage( SotStorageRef& parent, - const ::rtl::OUString& storageName, - const ::rtl::OUString& sN, - const com::sun::star::uno::Reference< - com::sun::star::container::XNameContainer > &rDialog, OCX_Control* pParent = NULL); - virtual ~OCX_MultiPage() - { - delete[] pCaption; - delete[] pIcon; - delete[] pPicture; - } - virtual sal_Bool Read(SvStorageStream *pS); - - using OCX_ContainerControl::Import; // to not hide the other two import methods - virtual sal_Bool Import(com::sun::star::uno::Reference< - com::sun::star::beans::XPropertySet> &rPropSet); - virtual sal_Bool Import(com::sun::star::uno::Reference< - com::sun::star::container::XNameContainer> - &rDialog); - virtual void ProcessControl( OCX_Control* pControl, SvStorageStream* pS, ContainerRecord& rec ); - /*sal_uInt8 for sal_uInt8 Word Struct*/ sal_uInt16 nIdentifier; sal_uInt16 nFixedAreaLen; sal_uInt8 pBlockFlags[4]; - sal_uInt32 fUnknown1; + sal_uInt32 nChildrenA; + sal_uInt32 nNextAvailableID; + sal_uInt32 nBooleanProperties; + sal_uInt32 nGroupCnt; + sal_uInt32 nZoom; - sal_uInt8 fUnknown2:1; + sal_uInt8 fUnknown1:1; sal_uInt8 fEnabled:1; sal_uInt8 fLocked:1; sal_uInt8 fBackStyle:1; - sal_uInt8 fUnknown3:4; + sal_uInt8 fUnknown2:4; - sal_uInt8 fUnknown4:8; + sal_uInt8 fUnknown3:8; - sal_uInt8 fUnknown5:7; + sal_uInt8 fUnknown4:7; sal_uInt8 fWordWrap:1; - sal_uInt8 fUnknown6:4; + sal_uInt8 fUnknown5:4; sal_uInt8 fAutoSize:1; - sal_uInt8 fUnknown7:3; + sal_uInt8 fUnknown6:3; sal_uInt32 nCaptionLen; sal_uInt16 nVertPos; sal_uInt16 nHorzPos; - sal_uInt8 nMousePointer; sal_uInt32 nBorderColor; - sal_uInt32 fUnknown8; - sal_uInt32 fUnknown9; + sal_uInt32 nDrawBuffer; + sal_uInt32 nShapeCookie; sal_uInt8 nKeepScrollBarsVisible; sal_uInt8 nCycle; - sal_uInt16 nBorderStyle; - sal_uInt16 nSpecialEffect; + sal_uInt8 nBorderStyle; + sal_uInt8 nMousePointer; + sal_uInt8 nSpecialEffect; sal_uInt16 nPicture; sal_uInt8 nPictureAlignment; sal_uInt8 nPictureSizeMode; bool bPictureTiling; sal_uInt16 nAccelerator; sal_uInt16 nIcon; + sal_uInt16 fUnknown7; char *pCaption; sal_uInt32 nScrollWidth; sal_uInt32 nScrollHeight; - + sal_uInt32 nScrollLeft; + sal_uInt32 nScrollTop; sal_uInt8 pIconHeader[20]; sal_uInt32 nIconLen; @@ -640,253 +601,91 @@ public: sal_uInt8 pPictureHeader[20]; sal_uInt32 nPictureLen; - sal_uInt8 *pPicture; private: - sal_Int32 mnCurrentPageStep; -}; - + OCX_ParentControl(); // not implemented + OCX_ParentControl(const OCX_ParentControl&); // not implemented +}; -class OCX_Page : public OCX_ContainerControl +class OCX_Page; +class OCX_MultiPage : public OCX_ParentControl { public: - OCX_Page( SotStorageRef& parentStorage, + OCX_MultiPage( SotStorageRef& parent, const ::rtl::OUString& storageName, const ::rtl::OUString& sN, const com::sun::star::uno::Reference< - com::sun::star::container::XNameContainer > &rDialog, OCX_Control* parent = NULL); - virtual ~OCX_Page() - { - delete[] pCaption; - delete[] pIcon; - delete[] pPicture; - } + com::sun::star::container::XNameContainer > &rDialog, OCX_Control* pParent = NULL); + virtual sal_Bool Read(SvStorageStream *pS); - using OCX_ContainerControl::Import; // to not hide the other two import methods + using OCX_ParentControl::Import; // to not hide the other two import methods virtual sal_Bool Import(com::sun::star::uno::Reference< - com::sun::star::container::XNameContainer> - &rDialog); -/* virtual sal_Bool Import(com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet> &rPropSet); -*/ - /*sal_uInt8 for sal_uInt8 Word Struct*/ - sal_uInt16 nIdentifier; - sal_uInt16 nFixedAreaLen; - sal_uInt8 pBlockFlags[4]; - - sal_uInt32 fUnknown1; - - sal_uInt8 fUnknown2:1; - sal_uInt8 fEnabled:1; - sal_uInt8 fLocked:1; - sal_uInt8 fBackStyle:1; - sal_uInt8 fUnknown3:4; - - sal_uInt8 fUnknown4:8; - - sal_uInt8 fUnknown5:7; - sal_uInt8 fWordWrap:1; - - sal_uInt8 fUnknown6:4; - sal_uInt8 fAutoSize:1; - sal_uInt8 fUnknown7:3; - - sal_uInt32 nCaptionLen; - sal_uInt16 nVertPos; - sal_uInt16 nHorzPos; - sal_uInt8 nMousePointer; - sal_uInt32 nBorderColor; - sal_uInt32 fUnknown8; - sal_uInt32 fUnknown9; - sal_uInt8 nKeepScrollBarsVisible; - sal_uInt8 nCycle; - sal_uInt16 nBorderStyle; - sal_uInt16 nSpecialEffect; - sal_uInt16 nPicture; - sal_uInt8 nPictureAlignment; - sal_uInt8 nPictureSizeMode; - bool bPictureTiling; - sal_uInt16 nAccelerator; - sal_uInt16 nIcon; - - char *pCaption; - - sal_uInt32 nScrollWidth; - sal_uInt32 nScrollHeight; + virtual void ProcessControl( OCX_Control* pControl, SvStorageStream* pS, ContainerRecord& rec ); +private: + sal_Int32 nActiveTab; + SotStorageStreamRef mXStream; + bool bHasTabs; + std::vector< rtl::OUString > sCaptions; + // order of Ids corrosponds to the order of captions above + std::vector< sal_Int32 > mPageIds; + std::hash_map< sal_Int32, OCX_Page* > idToPage; +}; - sal_uInt8 pIconHeader[20]; - sal_uInt32 nIconLen; - sal_uInt8 *pIcon; +class OCX_Page : public OCX_ParentControl +{ +public: + OCX_Page( SotStorageRef& parentStorage, + sal_Int32 nID, + const ::rtl::OUString& sN, + const com::sun::star::uno::Reference< + com::sun::star::container::XNameContainer > &rDialog, OCX_Control* parent = NULL); + virtual sal_Bool Read(SvStorageStream *pS); - sal_uInt8 pPictureHeader[20]; - sal_uInt32 nPictureLen; - sal_uInt8 *pPicture; + using OCX_ParentControl::Import; // to not hide the other two import methods + virtual sal_Bool Import(com::sun::star::uno::Reference< + com::sun::star::beans::XPropertySet> &rPropSet); + rtl::OUString msTitle; // #FIXME we should use the existing caption + sal_Int32 mnID; private: }; -class OCX_Frame : public OCX_ContainerControl +class OCX_Frame : public OCX_ParentControl { public: OCX_Frame( SotStorageRef& parent, - const ::rtl::OUString& storageName, - const ::rtl::OUString& sN, - const com::sun::star::uno::Reference< - com::sun::star::container::XNameContainer > &rDialog, OCX_Control* pParent = NULL); - virtual ~OCX_Frame() - { - delete[] pCaption; - delete[] pIcon; - delete[] pPicture; - } + const ::rtl::OUString& storageName, + const ::rtl::OUString& sN, + const com::sun::star::uno::Reference< + com::sun::star::container::XNameContainer > &rDialog, OCX_Control* pParent = NULL); virtual sal_Bool Read(SvStorageStream *pS); - using OCX_ContainerControl::Import; // to not hide the other two import methods + using OCX_ParentControl::Import; // to not hide the other two import methods virtual sal_Bool Import(com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet> &rPropSet); - - /*sal_uInt8 for sal_uInt8 Word Struct*/ - sal_uInt16 nIdentifier; - sal_uInt16 nFixedAreaLen; - sal_uInt8 pBlockFlags[4]; - - sal_uInt32 fUnknown1; - - sal_uInt8 fUnknown2:1; - sal_uInt8 fEnabled:1; - sal_uInt8 fLocked:1; - sal_uInt8 fBackStyle:1; - sal_uInt8 fUnknown3:4; - - sal_uInt8 fUnknown4:8; - - sal_uInt8 fUnknown5:7; - sal_uInt8 fWordWrap:1; - - sal_uInt8 fUnknown6:4; - sal_uInt8 fAutoSize:1; - sal_uInt8 fUnknown7:3; - - sal_uInt32 nCaptionLen; - sal_uInt16 nVertPos; - sal_uInt16 nHorzPos; - sal_uInt8 nMousePointer; - sal_uInt32 nBorderColor; - sal_uInt32 fUnknown8; - sal_uInt32 fUnknown9; - sal_uInt8 nKeepScrollBarsVisible; - sal_uInt8 nCycle; - sal_uInt16 nBorderStyle; - sal_uInt16 nSpecialEffect; - sal_uInt16 nPicture; - sal_uInt8 nPictureAlignment; - sal_uInt8 nPictureSizeMode; - bool bPictureTiling; - sal_uInt16 nAccelerator; - sal_uInt16 nIcon; - - char *pCaption; - - sal_uInt32 nScrollWidth; - sal_uInt32 nScrollHeight; - sal_uInt32 nScrollLeft; - sal_uInt32 nScrollTop; - - - sal_uInt8 pIconHeader[20]; - sal_uInt32 nIconLen; - sal_uInt8 *pIcon; - - sal_uInt8 pPictureHeader[20]; - sal_uInt32 nPictureLen; - sal_uInt8 *pPicture; -private: }; -class OCX_UserForm : public OCX_ContainerControl + +class OCX_UserForm : public OCX_ParentControl { public: OCX_UserForm( SotStorageRef& parent, - const ::rtl::OUString& storageName, - const ::rtl::OUString& sN, - const com::sun::star::uno::Reference< - com::sun::star::container::XNameContainer > &rDialog, - const com::sun::star::uno::Reference< - com::sun::star::lang::XMultiServiceFactory >& rMsf); - ~OCX_UserForm() - { - delete[] pCaption; - delete[] pIcon; - } - - virtual sal_Bool Read(SvStorageStream *pS); - - using OCX_ContainerControl::Import; // to not hide the other two import methods + const ::rtl::OUString& storageName, + const ::rtl::OUString& sN, + const com::sun::star::uno::Reference< + com::sun::star::container::XNameContainer > &rDialog, + const com::sun::star::uno::Reference< + com::sun::star::lang::XMultiServiceFactory >& rMsf); + using OCX_ParentControl::Import; // to not hide the other two import methods virtual sal_Bool Import( com::sun::star::uno::Reference< com::sun::star::container::XNameContainer> &rDialog); - - /*sal_uInt8 for sal_uInt8 Word Struct*/ - sal_uInt16 nIdentifier; - sal_uInt16 nFixedAreaLen; - sal_uInt8 pBlockFlags[4]; - - sal_uInt32 nChildrenA; - - sal_uInt8 fUnknown1:1; - sal_uInt8 fEnabled:1; - sal_uInt8 fLocked:1; - sal_uInt8 fBackStyle:1; - sal_uInt8 fUnknown2:4; - - sal_uInt8 fUnknown3:8; - - sal_uInt8 fUnknown4:7; - sal_uInt8 fWordWrap:1; - - sal_uInt8 fUnknown5:4; - sal_uInt8 fAutoSize:1; - sal_uInt8 fUnknown6:3; - - sal_uInt32 nCaptionLen; - sal_uInt16 nVertPos; - sal_uInt16 nHorzPos; - sal_uInt8 nMousePointer; - sal_uInt32 nBorderColor; - sal_uInt32 nDrawBuffer; - sal_uInt32 nChildrenB; - sal_uInt8 nKeepScrollBarsVisible; - sal_uInt8 nCycle; - sal_uInt16 nBorderStyle; - sal_uInt8 nSpecialEffect; - sal_uInt16 nPicture; - sal_uInt8 nPictureAlignment; - sal_uInt8 nPictureSizeMode; - bool bPictureTiling; - sal_uInt16 nAccelerator; - sal_uInt16 nIcon; - sal_uInt16 fUnknown7; - - char *pCaption; - - sal_uInt32 nScrollWidth; - sal_uInt32 nScrollHeight; - sal_uInt32 nScrollLeft; - sal_uInt32 nScrollTop; - - sal_uInt8 pIconHeader[20]; - sal_uInt32 nIconLen; - sal_uInt8 *pIcon; - - sal_uInt8 pPictureHeader[20]; - sal_uInt32 nPictureLen; - ::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; + com::sun::star::uno::Reference< + com::sun::star::uno::XComponentContext> mxCtx; }; @@ -1131,8 +930,6 @@ public: sal_uInt8 pPictureHeader[20]; sal_uInt32 nPictureLen; - ::rtl::OUString sImageUrl; - com::sun::star::uno::Reference< com::sun::star::graphic::XGraphicObject> mxGrfObj; bool mbTakeFocus; @@ -1194,7 +991,7 @@ public: fAutoSize(0),nCaptionLen(0),nVertPos(1),nHorzPos(7),nMousePointer(0), nBorderColor(0x80000006),nBorderStyle(0),nSpecialEffect(0), nPicture(0),nAccelerator(0),nIcon(0),pCaption(0),nIconLen(0),pIcon(0), - nPictureLen(0),pPicture(0) + nPictureLen(0) { msFormType = rtl::OUString::createFromAscii("com.sun.star.form.component.FixedText"); msDialogType = rtl::OUString::createFromAscii("com.sun.star.awt.UnoControlFixedTextModel"); @@ -1206,7 +1003,6 @@ public: ~OCX_Label() { if (pCaption) delete[] pCaption; if (pIcon) delete[] pIcon; - if (pPicture) delete[] pPicture; } sal_Bool Read(SotStorageStream *pS); @@ -1250,7 +1046,6 @@ public: sal_uInt8 pPictureHeader[20]; sal_uInt32 nPictureLen; - sal_uInt8 *pPicture; static OCX_Control *Create() { return new OCX_Label;} diff --git a/filter/source/msfilter/msocximex.cxx b/filter/source/msfilter/msocximex.cxx index bd957d032700..b6e975804ad2 100644 --- a/filter/source/msfilter/msocximex.cxx +++ b/filter/source/msfilter/msocximex.cxx @@ -521,7 +521,6 @@ void lclReadCharArray( SvStorageStream& rStrm, char*& rpcCharArr, sal_uInt32 nLe } } - /** Creates an OUString from a character array created with lclReadCharArray(). The passed parameters must match, that means the length field must be the @@ -549,6 +548,39 @@ OUString lclCreateOUString( const char* pcCharArr, sal_uInt32 nLenFld ) return svt::BinFilterUtils::CreateOUStringFromUniStringArray( pcCharArr, nBufSize ); } +void readArrayString( SotStorageStream *pS, std::vector< rtl::OUString >& sStringsOut, sal_Int32 nSize, long nStart ) +{ + unsigned long nFinish = pS->Tell() + nSize; + while ( pS->Tell() < nFinish ) + { + sal_Int32 nStringLen = 0; + *pS >> nStringLen; + sal_uInt32 nStringSize = lclGetBufferSize( nStringLen ); + sal_Char* pString = new sal_Char[ nStringSize ]; + pS->Read( pString, nStringSize ); + rtl::OUString sString = lclCreateOUString( pString, nStringLen ); + delete[] pString; + sStringsOut.push_back( sString ); + ReadAlign(pS, pS->Tell() - nStart, 4); + } +} + +OUString createSubStreamName( const sal_uInt32& subStorageId ) +{ + static OUString sI = OUString::createFromAscii("i"); + static OUString sZero = OUString::createFromAscii( "0" ); + OUStringBuffer buf( 6 ); + buf.append( sI ); + // for subStorage id < 10 stream name has leading '0' + // eg "i07" + if ( subStorageId < 10 ) + { + buf.append( sZero ); + } + buf.append( OUString::valueOf( (sal_Int32)subStorageId ) ); + return buf.makeStringAndClear(); +} + // export --------------------------------------------------------------------- /** This class implements writing a character array from a Unicode string. @@ -641,6 +673,44 @@ void SvxOcxString::WriteCharArray( SvStorageStream& rStrm ) const } } +class MultiPageProps +{ +public: + sal_uInt16 nIdentifier; // major & minor version + sal_uInt16 nFixedAreaLen; // size of record + sal_uInt8 pBlockFlags[4]; // size of record + sal_Int32 mnPageCount; + sal_Int32 mnID; + bool mbEnabled; + std::vector< sal_Int32 > mnIDs; + + MultiPageProps(); + bool Read(SotStorageStream *pS); +}; + +MultiPageProps::MultiPageProps() : nIdentifier(0), nFixedAreaLen(0), mnPageCount(0), mnID(0), mbEnabled( true ) +{ +} + +bool MultiPageProps::Read(SotStorageStream *pS) +{ + *pS >> nIdentifier >> nFixedAreaLen; + pS->Read( pBlockFlags, sizeof( pBlockFlags ) ); + if ( pBlockFlags[ 0 ] & 0x02 ) + *pS >> mnPageCount; + if ( pBlockFlags[ 0 ] & 0x04 ) + *pS >> mnID; + if ( pBlockFlags[ 0 ] & 0x08 ) + mbEnabled = false; + for ( sal_Int32 i=0; i<mnPageCount; ++i ) + { + sal_Int32 nID(0); + *pS >> nID; + mnIDs.push_back( nID ); + } + return true; +} + const sal_uInt16 USERFORM = (sal_uInt16)0xFF; const sal_uInt16 STDCONTAINER = (sal_uInt16)0xFE; @@ -666,48 +736,42 @@ 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 UNKNOWNCTRL = (sal_uInt16)0x7FFF; 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 +// following ActiveX controls are just for reference ( are NOT supported ) +const sal_uInt16 REFEDIT = (sal_uInt16)0x8001; +const sal_uInt16 CALENDAR = (sal_uInt16)0x8002; +const sal_uInt16 IMAGECOMBO = (sal_uInt16)0x8003; +const sal_uInt16 IMAGELIST = (sal_uInt16)0x8004; +const sal_uInt16 SLIDER = (sal_uInt16)0x8005; +const sal_uInt16 STATUSBAR = (sal_uInt16)0x8006; +const sal_uInt16 CHARTSPACE = (sal_uInt16)0x8007; + +// A set of common CLSIDs +// there are to identify the following ActiveX controls ( that appear in the ClassTable records ) // 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, }; +// 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, +}; + // 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[] = { @@ -738,238 +802,364 @@ 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 +const sal_uInt8 nSizeOfClsid = sizeof( aProgressID ); -bool lcl_handleActiveXControl( SvStorageStream *pS, sal_uInt16& nTypeID ) +struct ClsIdTypeIDPair { - 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 ) +// ClsIdTypeIDPair() : pClsID( NULL ), nTypeID( UNKNOWNCTRL ) {} + const sal_uInt8* pClsID; + const sal_uInt16 nTypeID; +}; + +ClsIdTypeIDPair ClsidList[] = { { aProgressID, PROGRESSBAR }, +// unsupported common activex controls +#ifdef DEBUG + { aRefEditID, REFEDIT }, + { aCalendarID, CALENDAR }, + { aImageComboID, IMAGECOMBO }, + { aImageListID, IMAGELIST }, + { aSliderID, SLIDER }, + { aStatusBarID, STATUSBAR }, + { aChartSpaceID, CHARTSPACE }, +#endif +}; + +typedef std::vector< ContainerRecord > ContainerRecordList; + +class FormObjectDepthTypeCount +{ + public: + sal_uInt8 depth; + sal_uInt8 TypeOrCount; + std::auto_ptr< sal_uInt8 > OptionalType; + FormObjectDepthTypeCount() : depth(0), TypeOrCount(0) {} + bool Read( SvStorageStream* pS ) + { + *pS >> depth >> TypeOrCount; + if ( TypeOrCount & 0x80 ) { - nTypeID = PROGRESSBAR; - OSL_TRACE("Found supported ***PROGRESSBAR*** ActiveX control"); - bRes = true; + OptionalType.reset( new sal_uInt8 ); + *pS >> *OptionalType; } -#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 + TypeOrCount = ( TypeOrCount >> 1 ); + return true; + } +}; + +class ClassTable +{ + sal_uInt16 nIdentifier; + sal_uInt16 nFixedAreaLen; + sal_uInt32 nContentFlags; + sal_uInt16 nClassTableFlags; + sal_uInt16 nVarFlags; + sal_Int32 nCountOfMethods; + sal_Int32 nDispidBind; + sal_uInt16 nGetBindIndex; + sal_uInt16 nPutBindIndex; + sal_uInt16 nBindType; + sal_uInt16 nGetValueIndex; + sal_uInt16 nPutValueIndex; + sal_uInt16 nValueType; + sal_uInt32 nDisidRowset; + sal_uInt16 nSetRowset; + sal_uInt8 pClsId[16]; + sal_uInt8 pDispEvent[16]; + sal_uInt8 pDefaultProg[16]; + sal_uInt16 nTypeId; +public: + ClassTable() : nIdentifier( 0 ) + ,nFixedAreaLen( 0 ) + ,nContentFlags(0) + ,nClassTableFlags(0) + ,nVarFlags(0) + ,nCountOfMethods(0) + ,nDispidBind(0) + ,nGetBindIndex(0) + ,nPutBindIndex(0) + ,nBindType(0) + ,nGetValueIndex(0) + ,nPutValueIndex(0) + ,nValueType(0) + ,nDisidRowset(0) + ,nSetRowset(0) + ,nTypeId(UNKNOWNCTRL) + + { + memset( pClsId, 0, sizeof( pClsId ) ); + memset( pDispEvent, 0, sizeof( pDispEvent ) ); + memset( pDefaultProg, 0, sizeof( pDefaultProg ) ); + } + bool Read( SvStorageStream* pS ) + { + long nStartPos = pS->Tell(); + *pS >> nIdentifier >> nFixedAreaLen >> nContentFlags; + bool bClsID( false ); + bool bDispEvent( false ); + bool bDefaultProg( false ); + if ( nContentFlags & 0x00000001 ) + bClsID = true; + if ( nContentFlags & 0x00000002 ) + bDispEvent = true; +// if ( nContentFlags & 0x00000004 ) ' not set should be 0 + if ( nContentFlags & 0x00000008 ) + bDefaultProg = true; + if ( nContentFlags & 0x00000010 ) + *pS >> nClassTableFlags >> nVarFlags; + if ( nContentFlags & 0x00000020 ) + *pS >> nCountOfMethods; + if ( nContentFlags & 0x00000040 ) + *pS >> nDispidBind; + if ( nContentFlags & 0x00000080 ) + *pS >> nGetBindIndex; + if ( nContentFlags & 0x00000100 ) + *pS >> nPutBindIndex; + if ( nContentFlags & 0x00000200 ) + *pS >> nBindType; + if ( nContentFlags & 0x00000400 ) + *pS >> nGetValueIndex; + if ( nContentFlags & 0x00000800 ) + *pS >> nPutValueIndex; + if ( nContentFlags & 0x00001000 ) + *pS >> nValueType; + if ( nContentFlags & 0x00002000 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + *pS >> nDisidRowset; + } + if ( nContentFlags & 0x00004000 ) + *pS >> nSetRowset; + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + // Extra Block + if ( bClsID ) + pS->Read( pClsId, sizeof( pClsId ) ); + if ( bDispEvent ) + pS->Read( pDispEvent, sizeof( pDispEvent ) ); + if ( bDefaultProg ) + pS->Read( pDefaultProg, sizeof( pDefaultProg ) ); + + sal_Int32 nNumIds = sizeof( ClsidList ) / sizeof( ClsidList[0] ); + + if ( bClsID ) { - OSL_TRACE("Unknown activeX ID !"); + for ( sal_Int32 index = 0; index < nNumIds; ++index ) + { + if ( memcmp( pClsId, ClsidList[ index ].pClsID, nSizeOfClsid ) == 0 ) + { + nTypeId = ClsidList[ index ].nTypeID; + OSL_TRACE( "... found activex control ClsidList[ %d ] and have given it TypeIdent 0x%x", index, nTypeId ); + } + } } + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + return true; } - return bRes; -} -typedef std::vector< ContainerRecord > ContainerRecordList; + sal_uInt16 getTypeId() { return nTypeId; } +}; -class ContainerRecReader +class OleSiteConcreteControl { - public: + sal_uInt16 nIdentifier; + sal_uInt16 nFixedAreaLen; + sal_uInt32 nContentFlags; +public: + OleSiteConcreteControl() : nIdentifier( 0 ), nFixedAreaLen( 0 ), nContentFlags(0) {} + bool Read( ContainerRecord& rec, SvStorageStream* pS ) + { + long nStartPos = pS->Tell(); + *pS >> nIdentifier >> nFixedAreaLen >> nContentFlags; + + bool bPosition( false ); + + sal_uInt32 nNameLen = 0; + // length of control name + if ( nContentFlags & 0x00000001 ) + *pS >> nNameLen; + // length of control tag + sal_uInt32 nTagLen = 0; + if( nContentFlags & 0x00000002 ) + *pS >> nTagLen; + // substorage id for frames + if( nContentFlags & 0x00000004 ) + *pS >> rec.nSubStorageId; + // help-context id + if( nContentFlags & 0x00000008 ) + pS->SeekRel( 4 ); + // option flags + if( nContentFlags & 0x00000010 ) + { + sal_uInt32 nBitFlags = 0; + *pS >> nBitFlags; + rec.bVisible = ( nBitFlags & 0x02 ); + rec.bTabStop = ( nBitFlags & 0x01 ); + } + // substream size + if( nContentFlags & 0x00000020 ) + *pS >> rec.nSubStreamLen; + // tabstop position + if( nContentFlags & 0x00000040 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 2 ); + *pS >> rec.nTabPos; + } + // control type + if( nContentFlags & 0x00000080 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 2 ); + *pS >> rec.nTypeIdent; + } + if( nContentFlags & 0x00000100 ) + bPosition = true; + sal_Int16 nGroupId = 0; + if( nContentFlags & 0x00000200 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 2 ); + *pS >> nGroupId; + } - virtual ~ContainerRecReader() {} + // length of infotip + sal_uInt32 nTipLen = 0; + if( nContentFlags & 0x00000800 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + *pS >> nTipLen; + } + sal_uInt32 nCntrlIdLen = 0; + if( nContentFlags & 0x00001000 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + *pS >> nCntrlIdLen; + } - virtual bool Read( OCX_ContainerControl* pContainerControl, SvStorageStream *pS) - { - *pS >> nNoRecords; - *pS >> nTotalLen; + // length of control source name + sal_uInt32 nCtrlSrcLen = 0; + if( nContentFlags & 0x00002000 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + *pS >> nCtrlSrcLen; + } - if ( isMultiPage ) + // length of row source name + sal_uInt32 nRowSrcLen = 0; + if( nContentFlags & 0x00004000 ) { - if ( !handleMultiPageHdr( pS ) ) - { - return false; - } + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + *pS >> nRowSrcLen; } - else + + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + // control name + sal_Char* pName = 0; + sal_uInt32 nNameBufSize = lclGetBufferSize( nNameLen ); + if( nNameBufSize > 0 ) { - if ( !handleStandardHdr( pS ) ) - { - return false; - } + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + pName = new char[ nNameBufSize ]; + pS->Read( pName, nNameBufSize ); + } + // control tag + sal_uInt32 nTagBufSize = lclGetBufferSize( nTagLen ); + if( nTagBufSize > 0 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + pS->SeekRel( nTagBufSize ); } - records.clear(); - for (sal_uInt32 nRecord = 0; nRecord < nNoRecords; ++nRecord) + // control position + if( bPosition ) { - // DR #134146# redo loading of FrameChild data + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + *pS >> rec.nLeft >> rec.nTop; + } - ContainerRecord rec; + // control infotip + sal_uInt32 nTipBufSize = lclGetBufferSize( nTipLen ); + if( nTipBufSize > 0 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + std::auto_ptr< sal_Char > pTipName; + pTipName.reset( new sal_Char[ nTipBufSize ] ); + pS->Read( pTipName.get(), nTipBufSize ); + rec.controlTip = lclCreateOUString( pTipName.get(), nTipLen ); + } + // control id + sal_uInt32 nCntrlIdSize = lclGetBufferSize( nCntrlIdLen ); + if( nCntrlIdSize > 0 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + pS->SeekRel( nCntrlIdSize ); + } + // control source name + sal_uInt32 nCtrlSrcBufSize = lclGetBufferSize( nCtrlSrcLen ); + if( nCtrlSrcBufSize > 0 ) + { + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + std::vector< sal_Char > pCtrlSrcName( nCtrlSrcBufSize ); + pS->Read( &pCtrlSrcName[0], nCtrlSrcBufSize ); + rec.sCtrlSource = lclCreateOUString( &pCtrlSrcName[0], 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 ); + std::vector< sal_Char > pRowSrcName( nRowSrcBufSize ); + pS->Read( &pRowSrcName[0], nRowSrcBufSize ); + rec.sRowSource = lclCreateOUString( &pRowSrcName[0], nRowSrcLen ); + OSL_TRACE("*** *** *** RowSourceName -> %s ", rtl::OUStringToOString( rec.sRowSource, RTL_TEXTENCODING_UTF8 ).getStr() ); + } - // record header - sal_uInt16 nId, nSize; - *pS >> nId >> nSize; - sal_Size nStartPos = pS->Tell(); - - // content flags - sal_uInt32 nContentFlags; - *pS >> nContentFlags; - - // length of control name - sal_uInt32 nNameLen = 0; - if( nContentFlags & 0x00000001 ) - *pS >> nNameLen; - // length of control tag - sal_uInt32 nTagLen = 0; - if( nContentFlags & 0x00000002 ) - *pS >> nTagLen; - // substorage id for frames - if( nContentFlags & 0x00000004 ) - *pS >> rec.nSubStorageId; - // help-context id - if( nContentFlags & 0x00000008 ) - pS->SeekRel( 4 ); - // option flags - if( nContentFlags & 0x00000010 ) - { - sal_uInt32 nBitFlags = 0; - *pS >> nBitFlags; - rec.bVisible = ( ( nBitFlags & 0x02 ) == 0x02 ); - } - // substream size - if( nContentFlags & 0x00000020 ) - *pS >> rec.nSubStreamLen; - // tabstop position - if( nContentFlags & 0x00000040 ) - *pS >> rec.nTabPos; - // 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 ) - { - ReadAlign( pS, pS->Tell() - nStartPos, 4 ); - *pS >> nTipLen; - } + ReadAlign( pS, pS->Tell() - nStartPos, 4 ); + rec.cName = lclCreateOUString(pName, nNameLen); + delete[] pName; + return true; + } +}; - sal_uInt32 nCntrlIdLen = 0; - if( nContentFlags & 0x00001000 ) - *pS >> nCntrlIdLen; +class ContainerRecReader +{ + public: - // length of control source name - sal_uInt32 nCtrlSrcLen = 0; - if( nContentFlags & 0x00002000 ) - { - ReadAlign( pS, pS->Tell() - nStartPos, 4 ); - *pS >> nCtrlSrcLen; - } + virtual ~ContainerRecReader() {} - // length of row source name - sal_uInt32 nRowSrcLen = 0; - if( nContentFlags & 0x00004000 ) - { - ReadAlign( pS, pS->Tell() - nStartPos, 4 ); - *pS >> nRowSrcLen; - } + virtual bool Read( OCX_ParentControl* pContainerControl, SvStorageStream *pS, std::vector< ClassTable >& rSiteClassInfo ) + { + *pS >> nNoRecords; + *pS >> nTotalLen; + long nStart = pS->Tell(); + for ( sal_uInt32 nSite = 0; nSite < nNoRecords; ) + { + FormObjectDepthTypeCount siteAndDepth; + siteAndDepth.Read( pS ); + nSite += ( siteAndDepth.OptionalType.get() ? siteAndDepth.TypeOrCount : 1 ); + } - // control name - sal_Char* pName = 0; - sal_uInt32 nNameBufSize = lclGetBufferSize( nNameLen ); - if( nNameBufSize > 0 ) - { - pName = new char[ nNameBufSize ]; - ReadAlign( pS, pS->Tell() - nStartPos, 4 ); - pS->Read( pName, nNameBufSize ); - } - // control tag - sal_uInt32 nTagBufSize = lclGetBufferSize( nTagLen ); - if( nTagBufSize > 0 ) - { - ReadAlign( pS, pS->Tell() - nStartPos, 4 ); - pS->SeekRel( nTagBufSize ); - } + ReadAlign(pS, pS->Tell() - nStart, 4); - // control position - if( nContentFlags & 0x00000100 ) - { - ReadAlign( pS, pS->Tell() - nStartPos, 4 ); - *pS >> rec.nLeft >> rec.nTop; - } + for (sal_uInt32 nRecord = 0; nRecord < nNoRecords; ++nRecord) + { - // control infotip - sal_uInt32 nTipBufSize = lclGetBufferSize( nTipLen ); - if( nTipBufSize > 0 ) - { - std::auto_ptr< sal_Char > pTipName; - pTipName.reset( new sal_Char[ nTipBufSize ] ); - ReadAlign( pS, pS->Tell() - nStartPos, 4 ); - pS->Read( pTipName.get(), nTipBufSize ); - rec.controlTip = lclCreateOUString( pTipName.get(), nTipLen ); - } - // control id - sal_uInt32 nCntrlIdSize = lclGetBufferSize( nCntrlIdLen ); - if( nCntrlIdSize > 0 ) - { - ReadAlign( pS, pS->Tell() - nStartPos, 4 ); - pS->SeekRel( nCntrlIdSize ); - } - // control source name - sal_uInt32 nCtrlSrcBufSize = lclGetBufferSize( nCtrlSrcLen ); - if( nCtrlSrcBufSize > 0 ) - { - ReadAlign( pS, pS->Tell() - nStartPos, 4 ); - 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 ) + ContainerRecord rec; + + OleSiteConcreteControl site; + site.Read( rec, pS ); + if ( rec.nTypeIdent >= ( UNKNOWNCTRL + 1 ) ) { - ReadAlign( pS, pS->Tell() - nStartPos, 4 ); - 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() ); + sal_uInt16 nIndex = rec.nTypeIdent - ( UNKNOWNCTRL + 1 ); + if ( nIndex < rSiteClassInfo.size() ) + rec.nTypeIdent = rSiteClassInfo[ nIndex ].getTypeId(); } - - // seek to end of data - pS->Seek( nStartPos + nSize ); - - rec.cName = lclCreateOUString(pName, nNameLen); - delete[] pName; - OCX_Control* pControl = NULL; + OSL_TRACE("** About to create control of type 0x%x with name %s from rec", rec.nTypeIdent, rtl::OUStringToOString( rec.cName, RTL_TEXTENCODING_UTF8 ).getStr() ); if( pContainerControl->createFromContainerRecord( rec, pControl ) && pControl ) { // propagate doc shell from parent pControl->pDocSh = pContainerControl->pDocSh; pContainerControl->ProcessControl( pControl, pS, rec ); + } else if ( rec.nTypeIdent & 0x8000 ) { @@ -987,90 +1177,12 @@ class ContainerRecReader return true; } + ContainerRecReader():nNoRecords(0), nTotalLen(0){} protected: - ContainerRecReader() : isMultiPage(false){} - bool isMultiPage; sal_uInt32 nNoRecords; sal_uInt32 nTotalLen; private: - bool handleStandardHdr( SvStorageStream* pS ) - { - 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; - } - - bool handleMultiPageHdr( SvStorageStream* pS ) - { - sal_uInt32 nUnknown_32b; // unknown 32 bit structure, flags ? - sal_uInt16 nUnknown_16b; // unknown 16 bit structure - sal_uInt16 nMysteryLen; // lenght of unknown sub record - - *pS >> nUnknown_32b; - *pS >> nUnknown_16b; - *pS >> nMysteryLen; - - pS->SeekRel( nMysteryLen ); - return true; - } - ContainerRecordList records; -}; - -class StdContainerRecReader : public ContainerRecReader -{ - public: - StdContainerRecReader(){} -}; - -class MultiPageContainerRecReader : public ContainerRecReader -{ - public: - MultiPageContainerRecReader() - { - // NP ( 27-01-05 ) - // Strictly speaking this approach shouldn't be necessary. - // It should be possible to have a common routine read the - // container record array and by examining the flags present in - // the record to determine we expect to read or not. - // In this case for a MultPage control there is no Top or Left - // values in the control record array, however time contraints - // and associated risk prevent further investigation of this - // at the moment. - // similar situation exists for the start of the container record - // which in the case of the MultiPage is different from - // UserForm & Frame ( the other containers ) - - isMultiPage = true; // tell the base class skip - } -}; - -class ContainerRecordReaderFac -{ - public: - static ContainerRecReader* instance( sal_uInt32 containerType ) - { - switch( containerType ) - { - case PAGE: - case FRAME: - case USERFORM: - case STDCONTAINER: - return new StdContainerRecReader(); - case MULTIPAGE: - return new MultiPageContainerRecReader(); - default: - DBG_ERROR("Illegal container type for factory"); - return NULL; - } - } - private: - ContainerRecordReaderFac(); }; } // namespace @@ -1273,6 +1385,7 @@ sal_Bool OCX_Control::Import(uno::Reference<container::XNameContainer> &rDialog } uno::Reference<beans::XPropertySet> xPropSet(xCreate, uno::UNO_QUERY); + if (!xPropSet.is()) return sal_False; @@ -2202,6 +2315,12 @@ sal_Bool OCX_TextBox::Import(com::sun::star::uno::Reference< } } + if ( sImageUrl.getLength() ) + { + aTmp <<= sImageUrl; + rPropSet->setPropertyValue( WW8_ASCII2STR("ImageURL"), aTmp); + } + aFontData.Import(rPropSet); return sal_True; } @@ -3648,8 +3767,15 @@ sal_Bool OCX_Label::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 ); } if (nIcon) { @@ -3669,325 +3795,61 @@ TypeName::TypeName(sal_Char *pName, sal_uInt32 nStoreId, sal_uInt32 nLen, sal_uI { } -OCX_ContainerControl::OCX_ContainerControl( SotStorageRef& parent, - const ::rtl::OUString& storageName, - const ::rtl::OUString& sN, - const uno::Reference< container::XNameContainer > &rParent, - OCX_Control* pParent ) : - OCX_Control(sN, pParent), mxParent(rParent), nNoRecords(0), nTotalLen(0), containerType( STDCONTAINER ) -{ - - mContainerStorage = parent->OpenSotStorage(storageName, - STREAM_READWRITE | - STREAM_NOCREATE | - STREAM_SHARE_DENYALL); - mContainerStream = mContainerStorage->OpenSotStream( - String(RTL_CONSTASCII_STRINGPARAM("f"), - RTL_TEXTENCODING_MS_1252), - STREAM_STD_READ | STREAM_NOCREATE); - mContainedControlsStream = mContainerStorage->OpenSotStream( String(RTL_CONSTASCII_STRINGPARAM("o"), - RTL_TEXTENCODING_MS_1252), - STREAM_STD_READ | STREAM_NOCREATE); -} -OCX_ContainerControl::~OCX_ContainerControl() -{ - CtrlIterator aEnd = mpControls.end(); - for (CtrlIterator aIter = mpControls.begin(); aIter != aEnd; ++ aIter ) - { - delete *aIter; - } -} - -// Really import should receive the parent e.g. a Userform, Frame or Multi Page -// and call import on its containees with itself ( up-called from -// the base class ) but... the reality is we have no containment model -// so we make sure rPropSet is always the parent Dialog - -sal_Bool OCX_ContainerControl::Import(uno::Reference<beans::XPropertySet>& /* rProps */ ) -{ - if ( !mxParent.is() ) - { - return sal_False; - } - CtrlIterator aEnd = mpControls.end(); -// int count = 0; - for (CtrlIterator aIter = mpControls.begin(); aIter != aEnd; ++ aIter ) - { - if ( !(*aIter)->Import( mxParent ) ) - { - return sal_False; - } - } - return sal_True; -} - -OUString OCX_ContainerControl::createSubStreamName( const sal_uInt32& subStorageId ) -{ - static OUString sI = OUString::createFromAscii("i"); - static OUString sZero = OUString::createFromAscii( "0" ); - OUStringBuffer buf( 6 ); - buf.append( sI ); - // for subStorage id < 10 stream name has leading '0' - // eg "i07" - if ( subStorageId < 10 ) - { - buf.append( sZero ); - } - buf.append( OUString::valueOf( (sal_Int32)subStorageId ) ); - return buf.makeStringAndClear(); -} - - -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: - pControl = new OCX_CommandButton; - break; - case LABEL: - pControl = new OCX_UserFormLabel(this); - break; - case TEXTBOX: - pControl = new OCX_TextBox; - break; - case LISTBOX: - pControl = new OCX_ListBox; - break; - case COMBOBOX: - pControl = new OCX_ComboBox; - break; - case CHECKBOX: - pControl = new OCX_CheckBox; - break; - case OPTIONBUTTON: - pControl = new OCX_OptionButton; - break; - case TOGGLEBUTTON: - pControl = new OCX_ToggleButton; - break; - case IMAGE: //Image - { - pControl = new OCX_Image; - break; - } - case PAGE: // Page - { - OUString sMSStore = createSubStreamName( record.nSubStorageId ); - pControl = new OCX_Page(mContainerStorage, sMSStore, - record.cName, mxParent, this); - break; - } - case MULTIPAGE: // MultiPage - { - OUString sMSStore = createSubStreamName( record.nSubStorageId ); - pControl = new OCX_MultiPage( mContainerStorage, sMSStore, - record.cName, mxParent, this); - break; - } - case FRAME: //Frame - { - OUString sFrameStore = createSubStreamName( record.nSubStorageId ); - pControl = new OCX_Frame(mContainerStorage, sFrameStore, - record.cName, mxParent, this); - - break; - } - case SPINBUTTON: //SpinButton - { - pControl = new OCX_SpinButton; - break; - } - case TABSTRIP: //TabStrip - { - pControl = new OCX_TabStrip; - break; - } - case SCROLLBAR: //ScrollBar - pControl = new OCX_ScrollBar; - break; - case PROGRESSBAR: //ProgressBar Active X control - pControl = new OCX_ProgressBar; - break; - default: - OSL_TRACE( "**** Unknown control 0x%x", record.nTypeIdent ); - DBG_ERROR( "Unknown control"); - return false; - } - pControl->sName = record.cName; - return true; -} - - -void addSeperator( std::vector< OCX_Control* >& dest ) -{ - OCX_Control* seperator = new OCX_CommandButton; - seperator->SetInDialog(true); - seperator->sName = C2S("GroupSeperator"); - dest.push_back( seperator ); -} - -void addRButtons( 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 ); - } -} - -void OCX_ContainerControl::ProcessControl(OCX_Control* pControl,SvStorageStream* /* pS */, ContainerRecord& rec ) -{ - SotStorageStreamRef oStream = mContainedControlsStream; - - // can insert into OO Dialog (e.g is this a supported dialog control)?? - if ( rec.nTypeIdent == TABSTRIP ) - { - // skip the record in the stream, discard the control - oStream->SeekRel( rec.nSubStreamLen ); - delete pControl; - } - else - { - // A container control needs to read the f stream in - // the folder ( substorage ) associated with this control - switch ( rec.nTypeIdent ) - { - 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 - pControl->mnTop = rec.nTop + mnTop; - pControl->mnLeft = rec.nLeft + mnLeft; - // MS tabIndex, pretty useless in OpenOffice land - // as tab indexes in MS are relative to parent container. - // However we need this value in order to set - // OpenOffice tab indices in a sensible way to - // reflect the ms tabbing from orig MS UserForm, see below - pControl->mnTabPos = rec.nTabPos; - pControl->SetInDialog(true); - pControl->mbVisible = rec.bVisible; - if ( mnStep ) - { - // If the container has a step then it should be - // applied to all containees - pControl->mnStep = mnStep; - } - pControl->msParentName = sName; - - // #117490# DR: container records provide size of substream, use it here... - - // remember initial position to set correct stream position - ULONG nStrmPos = oStream->Tell(); - // import control, may return with invalid stream position - pControl->FullRead(oStream); - // set stream to position behind substream of this control - oStream->Seek( nStrmPos + rec.nSubStreamLen ); - - mpControls.push_back( pControl ); - } -} - -sal_Bool OCX_ContainerControl::Read(SvStorageStream *pS) -{ - - if ( mpParent ) - { - mnBackColor = mpParent->mnBackColor; - } - - std::auto_ptr< ContainerRecReader > reader ( - ContainerRecordReaderFac::instance( containerType ) ); - - reader->Read( this, pS ); - // Need to honour the MS Tab Indexes. However MS tab indexes are - // relative to parent, this hack sorts the controls in each container - // based on the ms tab indexes. When import is called we create the - // controls in Open/Star office based on the order of the tab indexes, - // 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() ); - return true; -} - OCX_MultiPage::OCX_MultiPage( SotStorageRef& parent, const ::rtl::OUString& storageName, const ::rtl::OUString& sN, const uno::Reference< container::XNameContainer > &rDialog, OCX_Control* pParent): - OCX_ContainerControl(parent, storageName, sN, rDialog, pParent ), fUnknown1(0), fEnabled(1), - fLocked(0), fBackStyle(1), fWordWrap(1), fAutoSize(0), nCaptionLen(0), - nVertPos(1), nHorzPos(7), nMousePointer(0), nBorderColor(0x80000012), - 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), nIconLen(0), pIcon(0), nPictureLen(0), - pPicture(0) -{ - //msDialogType = C2U("NotSupported"); + OCX_ParentControl(parent, storageName, sN, rDialog, pParent ), bHasTabs( true ) + +{ msDialogType = C2U("com.sun.star.awt.UnoMultiPageModel"); mnForeColor = 0x80000012L, mnBackColor = 0x8000000FL; bSetInDialog = true;// UserForm control only aFontData.SetHasAlign(TRUE); - containerType = MULTIPAGE; - mnCurrentPageStep = 0; + nActiveTab = 0; + // open up the 'x' stream + mXStream = mContainerStorage->OpenSotStream( + String(RTL_CONSTASCII_STRINGPARAM("x"), + RTL_TEXTENCODING_MS_1252), + STREAM_STD_READ | STREAM_NOCREATE); } void OCX_MultiPage::ProcessControl(OCX_Control* pControl, SvStorageStream* /* pS */, ContainerRecord& rec ) { SotStorageStreamRef oStream = mContainedControlsStream; - OCX_Page *pPage = NULL; - if ( rec.nTypeIdent == PAGE ) - pPage = static_cast< OCX_Page* >( pControl ); - if ( pPage != NULL ) + if ( rec.nTypeIdent == TABSTRIP ) { - pPage->mnStep = ++mnCurrentPageStep; - - pPage->mnTop = mnTop;// move these to Page::import ? - pPage->mnLeft = mnLeft; - pPage->mnBackColor = mnBackColor; - - oStream = pPage->getContainerStream();; - // Position of controls is relative to pos of this MuliPage - // Control - pPage->FullRead( oStream ); + // TabStrip reads the 'o' stream + OCX_TabStrip oTabStrip; + oTabStrip.sName = C2S("FromMultiPage-o"); + oTabStrip.Read( mContainedControlsStream ); + sCaptions = oTabStrip.msItems; + bHasTabs = oTabStrip.bHasTabs; + nHeight = oTabStrip.nHeight; + nWidth = oTabStrip.nWidth; + } + else if ( rec.nTypeIdent == PAGE ) + { + OCX_Page *pPage = NULL; + pPage = static_cast< OCX_Page* >( pControl ); + if ( pPage != NULL ) + { + oStream = pPage->getContainerStream();; + // Position of controls is relative to pos of this MuliPage + // Control + pPage->FullRead( oStream ); + // nWidth & nHeight seem to screw up multipage control + pPage->nWidth = 0; + pPage->nHeight = 0; + pPage->mnBackColor = mnBackColor; + + mpControls.push_back( pPage ); + idToPage[ pPage->mnID ] = pPage; + } - mpControls.push_back( pPage ); } else { @@ -4001,110 +3863,78 @@ sal_Bool OCX_MultiPage::Read(SvStorageStream *pS) { // Unlike the other containers e.g. UserForm & Frame // the o stream is does not contain info for the contained controls - // ( e.g. the pages themselves ) but seems to be for the MultiPage - // itself - need to check this in more detail - - // For the moment skip read of the MultiPage specific properties - // not much point reading these as we can't display the multi page - // control or in fact any sort of tabbed layout, best we can do is - // import just the contained controls of the individual pages - // Note: the record skipped below ( does not contain the expected - // info on this control, that seems to be contained in the o stream, - // see comment above) + // 'o' stream contains a tabstrip control + // 'f' stream as usual ( info about the containees ) + // '01..09' ( etc. ) these streams contain the page controls + // 'x' stream, this contains an array of properties for each page followed + // by a set of properties for the multipage control itself + + // read the 'f' stream + OCX_ParentControl::Read(pS); + + // Read the 'x' stream + // consists of + // a) nTabs + 1 PageProperties ( which are little use to us ) + // => skip + // b) a MutliPageProperty ( which contains at least the page count and + // IDs of the pages ( and order ) - useful for associating correct page + // with correct tab + + OCX_Control skip(C2S("Dummy")); - skip.Read( pS ); - mnCurrentPageStep = mnStep; //( set step of of pages relative to step - //of this MultiPage ( e.g. emulate containment ) - return OCX_ContainerControl::Read(pS); + sal_Int32 nPagePropsToRead = sCaptions.size() + 1; + for ( sal_Int32 page = 0; page < nPagePropsToRead; ++page ) + skip.Read( mXStream ); + MultiPageProps multiPage; + multiPage.Read( mXStream ); + mPageIds = multiPage.mnIDs; + return true; } sal_Bool OCX_MultiPage::Import(com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet> &rPropSet) { - OCX_ContainerControl::Import( rPropSet ); - return sal_True; -} - -sal_Bool OCX_MultiPage::Import(com::sun::star::uno::Reference< - com::sun::star::container::XNameContainer> - &rDialog) -{ - uno::Reference<beans::XPropertySet> xPropSet( rDialog, uno::UNO_QUERY ); - - // Although MultiPage is not represeted by a "real" control we still - // need to propagate the backcolor of this logical parent - // ( the dialog or Frame or whatever ) to the children of this control. - // For example the controls contained in the Page of a - // MultiPage control use the parents backcolor ( e,g, - // Pages backcolor ) when trying to fake transparency - mnBackColor = mpParent->mnBackColor; - - 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 + uno::Any aTmp(&sName,getCppuType((OUString *)0)); + rPropSet->setPropertyValue( + OUString(RTL_CONSTASCII_USTRINGPARAM("Name")), aTmp); + if ( !bHasTabs ) + rPropSet->setPropertyValue( + OUString(RTL_CONSTASCII_USTRINGPARAM("Decoration")), uno::makeAny( sal_False ) ); + aTmp <<= ImportColor(mnBackColor); + rPropSet->setPropertyValue( WW8_ASCII2STR("BackgroundColor"), aTmp); + // apply caption/titles to pages + std::vector<sal_Int32>::iterator itCtrlId = mPageIds.begin(); + std::vector<sal_Int32>::iterator itCtrlId_end = mPageIds.end(); + std::vector< rtl::OUString >::iterator itCaption = sCaptions.begin(); + mpControls.clear(); + // need to sort the controls according to the order of the ids + for ( sal_Int32 index = 1 ; ( sCaptions.size() == idToPage.size() ) && itCtrlId != itCtrlId_end; ++itCtrlId, ++itCaption, ++index ) + { + std::hash_map< sal_Int32, OCX_Page* >::iterator it = idToPage.find( *itCtrlId ); + if ( it != idToPage.end() ) { - // 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"); + it->second->msTitle = *itCaption; + if ( it->second->mbVisible ) + nActiveTab = index; + mpControls.push_back( it->second ); - // 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 ); } - OSL_TRACE("*** Major problem, no dialog to add controls to "); - DBG_ERROR(" Major problem, no dialog to add controls to "); - return false; -} - + OCX_ParentControl::Import( rPropSet ); + rPropSet->setPropertyValue( WW8_ASCII2STR("MultiPageValue"), uno::makeAny( nActiveTab )); + return sal_True; +} OCX_Page::OCX_Page( SotStorageRef& parent, - const ::rtl::OUString& storageName, + sal_Int32 nId, const ::rtl::OUString& sN, const uno::Reference< container::XNameContainer > &rDialog, OCX_Control* pParent): - OCX_ContainerControl(parent, storageName, sN, rDialog, pParent ), - fUnknown1(0), fEnabled(1), fLocked(0), - fBackStyle(1), fWordWrap(1), fAutoSize(0), nCaptionLen(0), nVertPos(1), - nHorzPos(7), nMousePointer(0), nBorderColor(0x80000012), - 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), nIconLen(0), pIcon(0), nPictureLen(0), - pPicture(0) -{ - msDialogType = C2U("NotSupported"); + OCX_ParentControl(parent, createSubStreamName( nId ), sN, rDialog, pParent ), mnID( nId ) +{ + msDialogType = C2U("com.sun.star.awt.UnoPageModel"); mnForeColor = 0x80000012, mnBackColor = 0x8000000F, bSetInDialog = true;// UserForm control only @@ -4114,65 +3944,35 @@ OCX_Page::OCX_Page( SotStorageRef& parent, sal_Bool OCX_Page::Read(SvStorageStream *pS) { - long nStart = pS->Tell(); - *pS >> nIdentifier; - DBG_ASSERT(0x400==nIdentifier, - "A control that has a different identifier"); - *pS >> nFixedAreaLen; - pS->Read(pBlockFlags,4); - - pS->SeekRel( nFixedAreaLen - sizeof( pBlockFlags ) ); - - ReadAlign( pS, pS->Tell() - nStart, 4); - - if (pBlockFlags[2] & 0x10) - { - //Font Stuff.. - pS->SeekRel(0x1a); - sal_uInt8 nFontLen; - *pS >> nFontLen; - pS->SeekRel(nFontLen); - } - return OCX_ContainerControl::Read(pS); - + return OCX_ParentControl::Read(pS); } sal_Bool OCX_Page::Import(com::sun::star::uno::Reference< - com::sun::star::container::XNameContainer> - &rDialog) + com::sun::star::beans::XPropertySet> + &rPropSet) { + uno::Any aTmp(&sName,getCppuType((OUString *)0)); + rPropSet->setPropertyValue( + OUString(RTL_CONSTASCII_USTRINGPARAM("Name")), aTmp); + + if (msTitle.getLength()) + rPropSet->setPropertyValue( WW8_ASCII2STR("Title"), uno::makeAny( msTitle ) ); + + aTmp <<= ImportColor(mnBackColor); + rPropSet->setPropertyValue( WW8_ASCII2STR("BackgroundColor"), aTmp); + + // Calls import on contained controls + OCX_ParentControl::Import( rPropSet ); + return sal_True; - uno::Reference<beans::XPropertySet> xPropSet( rDialog, uno::UNO_QUERY ); - if ( xPropSet.is() ) - { - // apply Step to contained controls - CtrlIterator aEnd = mpControls.end(); - for (CtrlIterator aIter = mpControls.begin(); aIter != aEnd; ++ aIter ) - { - (*aIter)->mnStep = mnStep; - } - // Calls import on contained pages - return OCX_ContainerControl::Import( xPropSet ); - } - OSL_TRACE("*** Major problem, no dialog to add controls to "); - DBG_ERROR("*** Major problem, no dialog to add controls to "); - return sal_False; } OCX_Frame::OCX_Frame( SotStorageRef& parent, const ::rtl::OUString& storageName, const ::rtl::OUString& sN, - const uno::Reference< container::XNameContainer > &rDialog, OCX_Control* pParent): - OCX_ContainerControl(parent, storageName, sN, rDialog, pParent ),fUnknown1(0),fEnabled(1), fLocked(0), - fBackStyle(1), fWordWrap(1), fAutoSize(0), nCaptionLen(0), nVertPos(1), - nHorzPos(7), nMousePointer(0), nBorderColor(0x80000012), - 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) -{ - msDialogType = C2U("com.sun.star.awt.UnoControlGroupBoxModel"); + const uno::Reference< container::XNameContainer > &rDialog, OCX_Control* pParent): OCX_ParentControl(parent, storageName, sN, rDialog, pParent ) +{ + msDialogType = C2U("com.sun.star.awt.UnoFrameModel"); mnForeColor = 0x80000012; mnBackColor = 0x8000000F; bSetInDialog = true;// UserForm control only @@ -4182,159 +3982,7 @@ OCX_Frame::OCX_Frame( SotStorageRef& parent, sal_Bool OCX_Frame::Read(SvStorageStream *pS) { - long nStart = pS->Tell(); - *pS >> nIdentifier; - DBG_ASSERT(0x400==nIdentifier, - "A control that has a different identifier"); - *pS >> nFixedAreaLen; - pS->Read(pBlockFlags,4); - - if (pBlockFlags[0] & 0x01) - { - DBG_ASSERT(!this, "ARSE"); - } - if (pBlockFlags[0] & 0x02) - *pS >> mnBackColor; - if (pBlockFlags[0] & 0x04) - *pS >> mnForeColor; - if (pBlockFlags[0] & 0x08) - *pS >> fUnknown1; - if (pBlockFlags[0] & 0x40) - { - sal_uInt8 nTemp; - *pS >> nTemp; - fEnabled = (nTemp&0x04)>>2; - fBackStyle = (nTemp&0x08)>>3; - *pS >> nTemp; - *pS >> nTemp; - fWordWrap = (nTemp&0x80)>>7; - *pS >> nTemp; - fAutoSize = (nTemp&0x10)>>4; - } - if (pBlockFlags[0] & 0x80) - { - *pS >> nBorderStyle; - } - - ReadAlign(pS, pS->Tell() - nStart, 4); - - if (pBlockFlags[1] & 0x01) - *pS >> nMousePointer; - if (pBlockFlags[1] & 0x02) - *pS >> nKeepScrollBarsVisible; - if (pBlockFlags[1] & 0x20) - *pS >> fUnknown1; // another unknown 32 bit ( or is 8 or 16 bit with padding ? ) - - if (pBlockFlags[1] & 0x80) - { - ReadAlign(pS, pS->Tell() - nStart, 2); - *pS >> nIcon; - DBG_ASSERT(nIcon == 0xFFFF, "Unexpected nIcon"); - } - - bool bCaption = false; - - if (pBlockFlags[2] & 0x01) - *pS >> nCycle; - if (pBlockFlags[2] & 0x02) - *pS >> nSpecialEffect; - - if (pBlockFlags[2] & 0x04) - { - ReadAlign(pS, pS->Tell() - nStart, 4); - *pS >> nBorderColor; - } - - if (pBlockFlags[2] & 0x08) - { - ReadAlign(pS, pS->Tell() - nStart, 4); - *pS >> nCaptionLen; - bCaption = true; - } - - if (pBlockFlags[2] & 0x10) - { - ReadAlign(pS, pS->Tell() - nStart, 2); - sal_uInt16 nNoIdea; - *pS >> nNoIdea; - DBG_ASSERT(nNoIdea == 0xFFFF, "Expected 0xFFFF, (related to font ?)"); - } - - if (pBlockFlags[2] & 0x20) - { - ReadAlign(pS, pS->Tell() - nStart, 2); - *pS >> nPicture; - DBG_ASSERT(nPicture == 0xFFFF, "Unexpected nIcon"); - } - - if (pBlockFlags[2] & 0x80) - *pS >> nPictureAlignment; - - if (pBlockFlags[3] & 0x01) - bPictureTiling = true; - - if (pBlockFlags[3] & 0x02) - *pS >> nPictureSizeMode; - - if (pBlockFlags[3] & 0x04) - { - ReadAlign(pS, pS->Tell() - nStart, 4); - *pS >> fUnknown8; - } - - if (pBlockFlags[3] & 0x08) - { - ReadAlign(pS, pS->Tell() - nStart, 4); - *pS >> fUnknown9; - } - - ReadAlign(pS, pS->Tell() - nStart, 4); - *pS >> nWidth; - *pS >> nHeight; - *pS >> nScrollWidth; - *pS >> nScrollHeight; - - if (pBlockFlags[1] & 0x10) - { - *pS >> nScrollLeft; - *pS >> nScrollTop; - } - - if ( bCaption ) - { - lclReadCharArray( *pS, pCaption, nCaptionLen, pS->Tell() - nStart); - } - - OUString tempCaption = lclCreateOUString( pCaption, nCaptionLen ); - - if (nIcon) - { - pS->Read(pIconHeader,20); - *pS >> nIconLen; - pIcon = new sal_uInt8[nIconLen]; - 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.. - pS->SeekRel(0x1a); - sal_uInt8 nFontLen; - *pS >> nFontLen; - pS->SeekRel(nFontLen); - } - - return OCX_ContainerControl::Read( pS ); + return OCX_ParentControl::Read( pS ); } sal_Bool OCX_Frame::Import(com::sun::star::uno::Reference< @@ -4349,195 +3997,26 @@ sal_Bool OCX_Frame::Import(com::sun::star::uno::Reference< rPropSet->setPropertyValue( WW8_ASCII2STR("Label"), aTmp); } + aTmp <<= ImportColor(mnBackColor); + rPropSet->setPropertyValue( WW8_ASCII2STR("BackgroundColor"), aTmp); + // Calls import on contained controls - OCX_ContainerControl::Import( rPropSet ); + OCX_ParentControl::Import( rPropSet ); return sal_True; } + OCX_UserForm::OCX_UserForm( SotStorageRef& parent, const OUString& storageName, const OUString& sN, const ::uno::Reference< container::XNameContainer > &rDialog, const ::uno::Reference< lang::XMultiServiceFactory >& rMsf): - OCX_ContainerControl(parent, storageName, sN, rDialog), - nChildrenA(0), fEnabled(1), fLocked(0), - fBackStyle(1), fWordWrap(1), fAutoSize(0), nCaptionLen(0), nVertPos(1), - nHorzPos(7), nMousePointer(0), nBorderColor(0x80000012), nChildrenB(0), - 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) - { - mnForeColor = 0x80000012; - mnBackColor = 0x8000000F; - uno::Reference< beans::XPropertySet> xProps( rMsf, uno::UNO_QUERY); - if ( xProps.is() ) - { - xProps->getPropertyValue(C2S("DefaultContext")) >>= mxCtx; - } - aFontData.SetHasAlign(TRUE); - } -sal_Bool OCX_UserForm::Read(SvStorageStream *pS) -{ - long nStart = pS->Tell(); - *pS >> nIdentifier; - DBG_ASSERT(0x400==nIdentifier, - "A control that has a different identifier"); - *pS >> nFixedAreaLen; - pS->Read(pBlockFlags,4); - - if (pBlockFlags[0] & 0x01) + OCX_ParentControl(parent, storageName, sN, rDialog ) { - DBG_ASSERT(!this, "ARSE"); - } - if (pBlockFlags[0] & 0x02) - *pS >> mnBackColor; - if (pBlockFlags[0] & 0x04) - *pS >> mnForeColor; - if (pBlockFlags[0] & 0x08) - *pS >> nChildrenA; - if (pBlockFlags[0] & 0x40) - { - sal_uInt8 nTemp; - *pS >> nTemp; - fEnabled = (nTemp&0x04)>>2; - fBackStyle = (nTemp&0x08)>>3; - *pS >> nTemp; - *pS >> nTemp; - fWordWrap = (nTemp&0x80)>>7; - *pS >> nTemp; - fAutoSize = (nTemp&0x10)>>4; - } - if (pBlockFlags[0] & 0x80) - { - ReadAlign(pS, pS->Tell() - nStart, 4); - *pS >> nBorderStyle; - } -#if 0 - sal_uInt16 nFixedOrAlign; - *pS >> nFixedOrAlign; -#endif - if (pBlockFlags[1] & 0x01) - *pS >> nMousePointer; - if (pBlockFlags[1] & 0x02) - *pS >> nKeepScrollBarsVisible; - if (pBlockFlags[1] & 0x20) + uno::Reference< beans::XPropertySet> xProps( rMsf, uno::UNO_QUERY); + if ( xProps.is() ) { - sal_uInt32 nUnknown32; - *pS >> nUnknown32; + xProps->getPropertyValue(C2S("DefaultContext")) >>= mxCtx; } - if (pBlockFlags[1] & 0x80) - { - ReadAlign(pS, pS->Tell() - nStart, 2); - *pS >> nIcon; - DBG_ASSERT(nIcon == 0xFFFF, "Unexpected nIcon"); - } - if (pBlockFlags[2] & 0x01) - *pS >> nCycle; - if (pBlockFlags[2] & 0x02) - *pS >> nSpecialEffect; - - if (pBlockFlags[2] & 0x04) - { - ReadAlign(pS, pS->Tell() - nStart, 4); - *pS >> nBorderColor; - } - - if (pBlockFlags[2] & 0x10) - { - ReadAlign(pS, pS->Tell() - nStart, 2); - sal_uInt16 nNoIdea; - *pS >> nNoIdea; - DBG_ASSERT(nNoIdea == 0xFFFF, "Expected 0xFFFF, (related to font ?)"); - } - - if (pBlockFlags[2] & 0x20) - { - ReadAlign(pS, pS->Tell() - nStart, 2); - *pS >> nPicture; - DBG_ASSERT(nPicture == 0xFFFF, "Unexpected nIcon"); - } - - if (pBlockFlags[2] & 0x80) - *pS >> nPictureAlignment; - - if (pBlockFlags[3] & 0x01) - bPictureTiling = true; - - if (pBlockFlags[3] & 0x02) - *pS >> nPictureSizeMode; - - if (pBlockFlags[3] & 0x04) - { - ReadAlign(pS, pS->Tell() - nStart, 4); - *pS >> nChildrenB; - } - - ReadAlign(pS, pS->Tell() - nStart, 4); - *pS >> nDrawBuffer; - - ReadAlign(pS, pS->Tell() - nStart, 4); - *pS >> nWidth; - *pS >> nHeight; - *pS >> nScrollWidth; - *pS >> nScrollHeight; - - if (pBlockFlags[1] & 0x10) - { - *pS >> nScrollLeft; - *pS >> nScrollTop; - } - - if (nIcon) - { - pS->Read(pIconHeader,20); - *pS >> nIconLen; - pIcon = new sal_uInt8[nIconLen]; - pS->Read(pIcon,nIconLen); - } - - ReadAlign( pS, pS->Tell() - nStart, 4); - if (pBlockFlags[2] & 0x10) - { - //Font Stuff.. - pS->SeekRel(0x1a); - sal_uInt8 nFontLen; - *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; - // seems to be no. of trailing records, - // before container record starts proper - // ( unknown what these trailing records are for) - if ( numTrailingRecs ) - { - for ( sal_Int16 i = 0 ; numTrailingRecs ; --numTrailingRecs, ++i ) - { - sal_uInt16 nTypeID = 0; - if ( lcl_handleActiveXControl( pS, nTypeID ) ) - { - if ( nTypeID & 0x8000 ) // valid ActiveXID - mActiveXIDMap[ ( i | 0x8000 ) ] = nTypeID; - } - } - } - return OCX_ContainerControl::Read( pS ); } sal_Bool OCX_UserForm::Import( @@ -4563,9 +4042,15 @@ sal_Bool OCX_UserForm::Import( aTmp <<= sal_Int32( aAppFontSize.Height ); //100th mm xDialogPropSet->setPropertyValue(WW8_ASCII2STR("Height"), aTmp); + if ( sImageUrl.getLength() ) + { + aTmp <<= sImageUrl; + xDialogPropSet->setPropertyValue( WW8_ASCII2STR("ImageURL"), aTmp); + } uno::Reference<beans::XPropertySet> xPropSet( mxParent, uno::UNO_QUERY ); - OCX_ContainerControl::Import( xPropSet ); + OCX_ParentControl::Import( xPropSet ); + uno::Reference< frame::XModel > xModel( pDocSh ? pDocSh->GetModel() : NULL ); uno::Reference<io::XInputStreamProvider> xSource = xmlscript::exportDialogModel(mxParent, mxCtx, pDocSh->GetModel() ); @@ -5133,6 +4618,11 @@ sal_Bool OCX_CheckBox::Import(com::sun::star::uno::Reference< rPropSet->setPropertyValue( WW8_ASCII2STR("VerticalAlign"), aTmp ); aFontData.Import(rPropSet); + if ( sImageUrl.getLength() ) + { + aTmp <<= sImageUrl; + rPropSet->setPropertyValue( WW8_ASCII2STR("ImageURL"), aTmp); + } return(sal_True); } @@ -5592,38 +5082,248 @@ sal_Bool HTML_TextBox::ReadFontData(SotStorageStream * /*pS*/) return sal_True; } +sal_Bool HTML_TextBox::ReadFontData(SotStorageStream *pS) +{ + return sal_True; +} + // Doesn't really read anything but just skips the // record. sal_Bool OCX_TabStrip::Read(SotStorageStream *pS) { - const long skipLen = 0x18; + long nStart = pS->Tell(); *pS >> nIdentifier; DBG_ASSERT(nStandardId==nIdentifier, "A control that has a different identifier"); *pS >> nFixedAreaLen; pS->Read(pBlockFlags, sizeof(pBlockFlags)); - pS->SeekRel(skipLen); - *pS >> nNumTabs; - // skip to end of control - pS->SeekRel(nFixedAreaLen - sizeof(pBlockFlags) - sizeof(nNumTabs) - skipLen ); - return sal_True; -} -sal_Bool OCX_TabStrip::ReadFontData(SotStorageStream *pS) -{ - // Seems like there is a real font record followed by - // a number of blank records ( e.g. nFixedAreaLen = 0 ) - // The number of trailing blank records is equal to the number of tabs - OCX_Control::ReadFontData(pS); - for ( sal_uInt16 index = 0; index < nNumTabs; index++ ) + bool bSize = false; + bool bMultiRow = false; + bool bTooltips = true; + bool hasEmbeddedImage = false; + sal_Int32 nameSize = 0; + sal_Int32 tipStringSize = 0; + sal_Int32 nAcceleratorSize = 0; + sal_Int32 nItemSize = 0; + sal_Int32 nTagSize = 0; + if ( pBlockFlags[ 0 ] & 0x01 ) + { + //List index + ReadAlign(pS, pS->Tell() - nStart, 4); + sal_Int32 nOptional32 = 0; // + *pS >> nOptional32; + } + if (pBlockFlags[0] & 0x02) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> mnBackColor; + } + if (pBlockFlags[0] & 0x04) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> mnForeColor; + } + if (pBlockFlags[0] & 0x10) + bSize = true; + if (pBlockFlags[0] & 0x20) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nItemSize; + } + if (pBlockFlags[0] & 0x40) + { + sal_Int8 nOptional8 = 0; // mouse pointer + *pS >> nOptional8; + } + if (pBlockFlags[1] & 0x01) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + sal_Int32 nOptional32 = 0; // taborientation + *pS >> nOptional32; + } + if (pBlockFlags[1] & 0x02) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + sal_Int32 nOptional32 = 0; // tabstyle + *pS >> nOptional32; + if ( nOptional32 == 2 ) + bHasTabs =false; + } + if (pBlockFlags[1] & 0x04) + bMultiRow = true; + if (pBlockFlags[1] & 0x08) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + sal_Int32 nOptional32 = 0; // tabfixedwidth + *pS >> nOptional32; + } + if (pBlockFlags[1] & 0x10) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + sal_Int32 nOptional32 = 0; // tabfixedheight + *pS >> nOptional32; + } + if (pBlockFlags[1] & 0x20) + bTooltips = false; + + if (pBlockFlags[1] & 0x80) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> tipStringSize; + } + + if (pBlockFlags[2] & 0x02) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nameSize; + } + + if (pBlockFlags[2] & 0x04) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + sal_Int32 nOptional32 = 0; // variouspropertybits + *pS >> nOptional32; + } + + if (pBlockFlags[2] & 0x10) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + sal_Int32 nOptional32 = 0; // tabsallocated + *pS >> nOptional32; + } + + if (pBlockFlags[2] & 0x20) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nTagSize; + } + + if (pBlockFlags[2] & 0x40) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nNumTabs; + } + + if (pBlockFlags[2] & 0x80) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nAcceleratorSize; + } + + if (pBlockFlags[3] & 0x01) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + sal_Int16 nOptional16 = 0; // Mouse Icon + *pS >> nOptional16; + hasEmbeddedImage = true; + } + + // Extra block + if ( bSize ) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nWidth; + *pS >> nHeight; + } + if ( nItemSize ) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + // read the caption for each tab + readArrayString( pS, msItems, nItemSize, nStart ); + std::vector< rtl::OUString >::iterator it = msItems.begin(); + std::vector< rtl::OUString >::iterator it_end = msItems.end(); + for ( sal_Int32 i=0; it != it_end; ++i, ++it ) + OSL_TRACE(" Caption [ %d ] is %s", i, rtl::OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + + if ( tipStringSize ) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + // read the tip for each tab + std::vector< rtl::OUString > sTips; + readArrayString( pS, sTips, tipStringSize, nStart ); + std::vector< rtl::OUString >::iterator it = sTips.begin(); + std::vector< rtl::OUString >::iterator it_end = sTips.end(); + for ( sal_Int32 i=0; it != it_end; ++i, ++it ) + OSL_TRACE(" Tip [ %d ] is %s", i, rtl::OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + + if ( nameSize ) { - OCX_Control::Read(pS); // read trailing records + ReadAlign(pS, pS->Tell() - nStart, 4); + // read the name for each tab + std::vector< rtl::OUString > sNames; + readArrayString( pS, sNames, nameSize, nStart ); + std::vector< rtl::OUString >::iterator it = sNames.begin(); + std::vector< rtl::OUString >::iterator it_end = sNames.end(); + for ( sal_Int32 i=0; it != it_end; ++i, ++it ) + OSL_TRACE(" Name [ %d ] is %s", i, rtl::OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + + if ( nTagSize ) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + // read the name for each tab + std::vector< rtl::OUString > sTags; + readArrayString( pS, sTags, nTagSize, nStart ); + std::vector< rtl::OUString >::iterator it = sTags.begin(); + std::vector< rtl::OUString >::iterator it_end = sTags.end(); + for ( sal_Int32 i=0; it != it_end; ++i, ++it ) + OSL_TRACE(" Tag [ %d ] is %s", i, rtl::OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + + if ( nAcceleratorSize ) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + // read the name for each tab + std::vector< rtl::OUString > sAccelerators; + readArrayString( pS, sAccelerators, nAcceleratorSize, nStart ); + std::vector< rtl::OUString >::iterator it = sAccelerators.begin(); + std::vector< rtl::OUString >::iterator it_end = sAccelerators.end(); + for ( sal_Int32 i=0; it != it_end; ++i, ++it ) + OSL_TRACE(" Accelerator [ %d ] is %s", i, rtl::OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + + // Stream data + if ( hasEmbeddedImage ) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + sal_uInt8 pPictureHeader[20]; + sal_uInt32 nPictureLen(0); + 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 ); + } + + ReadAlign(pS, pS->Tell() - nStart, 4); + OCX_Control::ReadFontData(pS); // read textprops + ReadAlign(pS, pS->Tell() - nStart, 4); + for ( sal_Int32 i = 0; i < nNumTabs; ++i ) + { + sal_uInt32 TabStripTabFlags(0); + *pS >> TabStripTabFlags; } return sal_True; } +sal_Bool OCX_TabStrip::ReadFontData(SotStorageStream* /* pS */) +{ + // OCX_TabStrip::Read includes the text props + return true; +} + sal_Bool OCX_Image::Read(SotStorageStream *pS) { ULONG nStart = pS->Tell(); @@ -5707,12 +5407,10 @@ sal_Bool OCX_Image::Read(SotStorageStream *pS) if ( hasEmbeddedImage ) { - //image follows this block - //len of image is 0x14 relative to end of this block - pS->Seek( pS->Tell() + 0x14 ); - - sal_uInt32 nImageLen = 0; - *pS >> nImageLen; + sal_uInt8 pPictureHeader[20]; + sal_uInt32 nPictureLen(0); + pS->Read(pPictureHeader,20); + *pS >> nPictureLen; long imagePos = pS->Tell(); @@ -5723,7 +5421,7 @@ sal_Bool OCX_Image::Read(SotStorageStream *pS) sImageUrl = sImageUrl + mxGrfObj->getUniqueID(); } // make sure the stream position should be pointing after the image - pS->Seek( imagePos + nImageLen ); + pS->Seek( imagePos + nPictureLen ); } return sal_True; } @@ -6400,6 +6098,375 @@ sal_Bool OCX_ProgressBar::Import(uno::Reference< beans::XPropertySet > &rPropSet rPropSet->setPropertyValue( WW8_ASCII2STR("Enabled"), uno::makeAny( sal_False ) ); return sal_True; } + // ============================================================================ +OCX_ParentControl::OCX_ParentControl( SotStorageRef& parent, const OUString& storageName, const OUString& sN, const ::uno::Reference< container::XNameContainer > &rParent, OCX_Control* pParent ) : OCX_Control(sN, pParent), mxParent(rParent), nNextAvailableID(0), nBooleanProperties(0), nGroupCnt(0), nZoom(0), fEnabled(1), fLocked(0), fBackStyle(1), fWordWrap(1), fAutoSize(0), nCaptionLen(0), nVertPos(1), nHorzPos(7), nBorderColor(0x80000012), nShapeCookie(0), nKeepScrollBarsVisible(3), nCycle(0), nBorderStyle(0), nMousePointer(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) +{ + mnForeColor = 0x80000012; + mnBackColor = 0x8000000F; + aFontData.SetHasAlign(TRUE); + mContainerStorage = parent->OpenSotStorage(storageName, + STREAM_READWRITE | + STREAM_NOCREATE | + STREAM_SHARE_DENYALL); + mContainerStream = mContainerStorage->OpenSotStream( + String(RTL_CONSTASCII_STRINGPARAM("f"), + RTL_TEXTENCODING_MS_1252), + STREAM_STD_READ | STREAM_NOCREATE); + mContainedControlsStream = mContainerStorage->OpenSotStream( String(RTL_CONSTASCII_STRINGPARAM("o"), + RTL_TEXTENCODING_MS_1252), + STREAM_STD_READ | STREAM_NOCREATE); +} + +OCX_ParentControl::~OCX_ParentControl() +{ + CtrlIterator aEnd = mpControls.end(); + for (CtrlIterator aIter = mpControls.begin(); aIter != aEnd; ++ aIter ) + { + delete *aIter; + } +} + +sal_Bool OCX_ParentControl::Import(uno::Reference<beans::XPropertySet>& rProps ) +{ + // #FIXME we probably don't need this (fake) parent (mxParen) which is the dialog iirc + if ( !mxParent.is() ) + { + return sal_False; + } + CtrlIterator aEnd = mpControls.end(); +// int count = 0; + for (CtrlIterator aIter = mpControls.begin(); aIter != aEnd; ++ aIter ) + { + uno::Reference< container::XNameContainer > xNameContainer( rProps, uno::UNO_QUERY ); + if ( !(*aIter)->Import( xNameContainer ) ) + { + return sal_False; + } + } + return sal_True; +} + +bool OCX_ParentControl::createFromContainerRecord( const ContainerRecord& record, OCX_Control*& pControl ) +{ + pControl = NULL; + switch ( record.nTypeIdent) + { + case CMDBUTTON: + pControl = new OCX_CommandButton; + break; + case LABEL: + pControl = new OCX_UserFormLabel(this); + break; + case TEXTBOX: + pControl = new OCX_TextBox; + break; + case LISTBOX: + pControl = new OCX_ListBox; + break; + case COMBOBOX: + pControl = new OCX_ComboBox; + break; + case CHECKBOX: + pControl = new OCX_CheckBox; + break; + case OPTIONBUTTON: + pControl = new OCX_OptionButton; + break; + case TOGGLEBUTTON: + pControl = new OCX_ToggleButton; + break; + case IMAGE: //Image + { + pControl = new OCX_Image; + break; + } + case PAGE: // Page + { + pControl = new OCX_Page(mContainerStorage, record.nSubStorageId, + record.cName, mxParent, this); + break; + } + case MULTIPAGE: // MultiPage + { + OUString sMSStore = createSubStreamName( record.nSubStorageId ); + pControl = new OCX_MultiPage( mContainerStorage, sMSStore, + record.cName, mxParent, this); + break; + } + case FRAME: //Frame + { + OUString sFrameStore = createSubStreamName( record.nSubStorageId ); + pControl = new OCX_Frame(mContainerStorage, sFrameStore, + record.cName, mxParent, this); + + break; + } + case SPINBUTTON: //SpinButton + { + pControl = new OCX_SpinButton; + break; + } + case TABSTRIP: //TabStrip + { + pControl = new OCX_TabStrip; + break; + } + case SCROLLBAR: //ScrollBar + pControl = new OCX_ScrollBar; + break; + case PROGRESSBAR: //ProgressBar Active X control + pControl = new OCX_ProgressBar; + break; + default: + OSL_TRACE( "**** Unknown control 0x%x", record.nTypeIdent ); + DBG_ERROR( "Unknown control"); + return false; + } + pControl->sName = record.cName; + + pControl->msToolTip = record.controlTip; + pControl->mnTop = record.nTop; + pControl->mnLeft = record.nLeft; + // MS tabIndex, pretty useless in OpenOffice land + // as tab indexes in MS are relative to parent container. + // However we need this value in order to set + // OpenOffice tab indices in a sensible way to + // reflect the ms tabbing from orig MS UserForm, see below + pControl->mnTabPos = record.nTabPos; + pControl->SetInDialog(true); + pControl->mbVisible = record.bVisible; + + return true; +} + +void OCX_ParentControl::ProcessControl(OCX_Control* pControl,SvStorageStream* /* pS */, ContainerRecord& rec ) +{ + SotStorageStreamRef oStream = mContainedControlsStream; + + // can insert into OO Dialog (e.g is this a supported dialog control)?? + if ( rec.nTypeIdent == TABSTRIP ) + { + // skip the record in the stream, discard the control + oStream->SeekRel( rec.nSubStreamLen ); + delete pControl; + } + else + { + // 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 ) + { + OCX_ParentControl* pContainer = + static_cast< OCX_ParentControl* >( pControl ); + oStream = pContainer->getContainerStream(); + } + // #117490# DR: container records provide size of substream, use it here... + + // remember initial position to set correct stream position + ULONG nStrmPos = oStream->Tell(); + // import control, may return with invalid stream position + pControl->FullRead(oStream); + // set stream to position behind substream of this control + oStream->Seek( nStrmPos + rec.nSubStreamLen ); + } +} + +sal_Bool OCX_ParentControl::Read(SvStorageStream *pS) +{ + long nStart = pS->Tell(); + + *pS >> nIdentifier; + DBG_ASSERT(0x400==nIdentifier, + "A control that has a different identifier"); + *pS >> nFixedAreaLen; + pS->Read(pBlockFlags,4); + + bool bExtraSize = false; + bool bLogicalSize = false; + bool bScrollPosition = false; + bool bFont = false; + if (pBlockFlags[0] & 0x01) + { + DBG_ASSERT(!this, "ARSE"); + } + if (pBlockFlags[0] & 0x02) + *pS >> mnBackColor; + if (pBlockFlags[0] & 0x04) + *pS >> mnForeColor; + if (pBlockFlags[0] & 0x08) + *pS >> nNextAvailableID; + if (pBlockFlags[0] & 0x40) + *pS >> nBooleanProperties; + ReadAlign(pS, pS->Tell() - nStart, 4); + if (pBlockFlags[0] & 0x80) + { + *pS >> nBorderStyle; + } + if (pBlockFlags[1] & 0x01) + *pS >> nMousePointer; + if (pBlockFlags[1] & 0x02) + *pS >> nKeepScrollBarsVisible; + if (pBlockFlags[1] & 0x04) + bExtraSize = true; + if (pBlockFlags[1] & 0x08) + bLogicalSize = true; + if (pBlockFlags[1] & 0x10) + bScrollPosition = true; + if (pBlockFlags[1] & 0x20) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nGroupCnt; + } + + if (pBlockFlags[1] & 0x80) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nIcon; + DBG_ASSERT(nIcon == 0xFFFF, "Unexpected nIcon"); + } + if (pBlockFlags[2] & 0x01) + *pS >> nCycle; + if (pBlockFlags[2] & 0x02) + *pS >> nSpecialEffect; + if (pBlockFlags[2] & 0x04) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nBorderColor; + } + if (pBlockFlags[2] & 0x08) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nCaptionLen; + } + + if (pBlockFlags[2] & 0x10) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + sal_uInt16 nNoIdea; + *pS >> nNoIdea; + DBG_ASSERT(nNoIdea == 0xFFFF, "Expected 0xFFFF, (related to font ?)"); + bFont = true; + } + if (pBlockFlags[2] & 0x20) + { + ReadAlign(pS, pS->Tell() - nStart, 2); + *pS >> nPicture; + DBG_ASSERT(nPicture == 0xFFFF, "Unexpected nIcon"); + } + + if (pBlockFlags[2] & 0x40) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nZoom; + } + if (pBlockFlags[2] & 0x80) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nPictureAlignment; + } + + if (pBlockFlags[3] & 0x01) + bPictureTiling = true; + + if (pBlockFlags[3] & 0x02) + *pS >> nPictureSizeMode; + + if (pBlockFlags[3] & 0x04) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nShapeCookie; + } + if (pBlockFlags[3] & 0x08) + { + ReadAlign(pS, pS->Tell() - nStart, 4); + *pS >> nDrawBuffer; + } + + ReadAlign(pS, pS->Tell() - nStart, 4); + // Extra + if ( bExtraSize ) + { + *pS >> nWidth; + *pS >> nHeight; + } + if ( bLogicalSize ) + { + *pS >> nScrollWidth; + *pS >> nScrollHeight; + } + if ( bScrollPosition ) + { + *pS >> nScrollLeft; + *pS >> nScrollTop; + } + if ( nCaptionLen ) + { + sal_uInt32 nCaptionSize = lclGetBufferSize( nCaptionLen ); + if ( nCaptionSize ) + { + pCaption = new sal_Char[ nCaptionSize ]; + pS->Read( pCaption, nCaptionSize ); + } + } + + ReadAlign(pS, pS->Tell() - nStart, 4); + + // StreamData + if (nIcon) + { + pS->Read(pIconHeader,20); + *pS >> nIconLen; + pIcon = new sal_uInt8[nIconLen]; + pS->Read(pIcon,nIconLen); + } + if ( bFont ) + { + //Font Stuff.. + pS->SeekRel(0x1a); + sal_uInt8 nFontLen; + *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 ); + } + // FormSiteData + std::vector< ClassTable > siteClassInfo; + if ( ( nBooleanProperties & 0x00008000 ) == 0x0) + { + sal_Int16 numTrailingRecs = 0; + *pS >> numTrailingRecs; + if ( numTrailingRecs ) + { + for ( ; numTrailingRecs ; --numTrailingRecs ) + { + ClassTable cacheClass; + cacheClass.Read( pS ); + siteClassInfo.push_back( cacheClass ); + } + } + } + // Sites + ContainerRecReader reader; + reader.Read( this, pS, siteClassInfo ); + + return true; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/msfilter/msvbahelper.cxx b/filter/source/msfilter/msvbahelper.cxx index 5baf69bf11a5..95b7a7d6ad93 100644 --- a/filter/source/msfilter/msvbahelper.cxx +++ b/filter/source/msfilter/msvbahelper.cxx @@ -37,6 +37,7 @@ #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> #include <com/sun/star/document/XDocumentProperties.hpp> #include <com/sun/star/document/XDocumentInfoSupplier.hpp> +#include <com/sun/star/script/vba/XVBACompatibility.hpp> #include <tools/urlobj.hxx> #include <osl/file.hxx> #include <unotools/pathoptions.hxx> @@ -287,15 +288,15 @@ VBAMacroResolvedInfo resolveVBAMacro( SfxObjectShell* pShell, const rtl::OUStrin { // Ok, if we have no Container specified then we need to search them in order, this document, template this document created from, global templates, // get the name of Project/Library for 'this' document - rtl::OUString sThisProject; - BasicManager* pBasicMgr = pShell-> GetBasicManager(); - if ( pBasicMgr ) + rtl::OUString sThisProject = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Standard") ); + try { - if ( pBasicMgr->GetName().Len() ) - sThisProject = pBasicMgr->GetName(); - else // cater for the case where VBA is not enabled - sThisProject = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Standard") ); + uno::Reference< beans::XPropertySet > xProps( pShell->GetModel(), uno::UNO_QUERY_THROW ); + uno::Reference< script::vba::XVBACompatibility > xVBAMode( xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("BasicLibraries") ) ), uno::UNO_QUERY_THROW ); + sThisProject = xVBAMode->getProjectName(); } + catch( uno::Exception& /*e*/) {} + sSearchList.push_back( sThisProject ); // First Lib to search if ( xPrjNameCache.is() ) { diff --git a/oox/inc/oox/helper/containerhelper.hxx b/oox/inc/oox/helper/containerhelper.hxx index 55c609924720..9a0a0774c43b 100644 --- a/oox/inc/oox/helper/containerhelper.hxx +++ b/oox/inc/oox/helper/containerhelper.hxx @@ -125,6 +125,13 @@ public: forEach( ::boost::bind( pFunc, _1, aParam1, aParam2, aParam3 ) ); } + /** Calls the passed member function of ObjType on every contained object, + automatically skips all elements that are empty references. */ + template< typename FuncType, typename ParamType1, typename ParamType2, typename ParamType3, typename ParamType4 > + inline void forEachMem( FuncType pFunc, ParamType1 aParam1, ParamType2 aParam2, ParamType3 aParam3, ParamType4 aParam4 ) const + { + forEach( ::boost::bind( pFunc, _1, aParam1, aParam2, aParam3, aParam4 ) ); + } /** Calls the passed functor for every contained object. Passes the index as first argument and the object reference as second argument to rFunctor. */ template< typename FunctorType > @@ -282,6 +289,13 @@ public: { forEach( ::boost::bind( pFunc, _1, aParam1, aParam2, aParam3 ) ); } + /** Calls the passed member function of ObjType on every contained object, + automatically skips all elements that are empty references. */ + template< typename FuncType, typename ParamType1, typename ParamType2, typename ParamType3, typename ParamType4 > + inline void forEachMem( FuncType pFunc, ParamType1 aParam1, ParamType2 aParam2, ParamType3 aParam3, ParamType4 aParam4 ) const + { + forEach( ::boost::bind( pFunc, _1, aParam1, aParam2, aParam3, aParam4 ) ); + } /** Calls the passed functor for every contained object. Passes the key as first argument and the object reference as second argument to rFunctor. */ template< typename FunctorType > diff --git a/oox/inc/oox/ole/axcontrol.hxx b/oox/inc/oox/ole/axcontrol.hxx index 4152857cad73..eccd5865cfa9 100644 --- a/oox/inc/oox/ole/axcontrol.hxx +++ b/oox/inc/oox/ole/axcontrol.hxx @@ -31,6 +31,7 @@ #include <boost/shared_ptr.hpp> #include "oox/helper/binarystreambase.hxx" +#include "oox/helper/propertyset.hxx" #include "oox/ole/axbinaryreader.hxx" #include "oox/ole/olehelper.hxx" @@ -38,6 +39,7 @@ namespace com { namespace sun { namespace star { namespace awt { class XControlModel; } namespace container { class XIndexContainer; } namespace drawing { class XDrawPage; } + namespace frame { class XModel; } namespace form { class XFormsSupplier; } namespace lang { class XMultiServiceFactory; } } } } @@ -148,6 +150,7 @@ class ControlConverter { public: explicit ControlConverter( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& rxDocModel, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr = true ); virtual ~ControlConverter(); @@ -186,6 +189,14 @@ public: sal_Int32 nMin, sal_Int32 nMax, sal_Int32 nPosition, sal_Int32 nSmallChange, sal_Int32 nLargeChange, bool bAwtModel ) const; + /** Binds the passed control model to the passed data sources. The + implementation will check which source types are supported. */ + void bindToSources( + const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel >& rxCtrlModel, + const ::rtl::OUString& rCtrlSource, + const ::rtl::OUString& rRowSource, + sal_Int32 nRefSheet = 0 ) const; + // ActiveX (Forms 2.0) specific conversion -------------------------------- /** Converts the Forms 2.0 background formatting to UNO properties. */ @@ -239,7 +250,10 @@ public: sal_Int32 nOrientation ) const; private: + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > mxDocModel; const GraphicHelper& mrGraphicHelper; + mutable PropertySet maAddressConverter; + mutable PropertySet maRangeConverter; bool mbDefaultColorBgr; }; @@ -805,7 +819,7 @@ class EmbeddedForm : public ControlConverter { public: explicit EmbeddedForm( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxModelFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& rxDocModel, const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& rxDrawPage, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr = true ); diff --git a/oox/inc/oox/ole/vbacontrol.hxx b/oox/inc/oox/ole/vbacontrol.hxx index 8f419cd6290e..df25e746bc6d 100644 --- a/oox/inc/oox/ole/vbacontrol.hxx +++ b/oox/inc/oox/ole/vbacontrol.hxx @@ -84,12 +84,19 @@ public: ApiControlType eCtrlType, sal_Int32 nCtrlIndex ) const; + /** Binds the passed control model to the data sources. The implementation + will check which source types are supported. */ + void bindToSources( + const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel >& rxCtrlModel, + const ControlConverter& rConv ) const; + protected: ::rtl::OUString maName; /// Name of the control. ::rtl::OUString maTag; /// User defined tag. ::rtl::OUString maToolTip; /// Tool tip for the control. - ::rtl::OUString maLinkedCell; /// Linked cell for the control value in a spreadsheet. - ::rtl::OUString maSourceRange; /// Source data for the control in a spreadsheet. + ::rtl::OUString maControlSource; /// Linked cell for the control value in a spreadsheet. + ::rtl::OUString maRowSource; /// Source data for the control in a spreadsheet. + AxPairData maPos; /// Position in parent container. sal_Int32 mnId; /// Control identifier. sal_Int32 mnHelpContextId; /// Help context identifier. @@ -161,13 +168,7 @@ private: /** Imports the site models of all embedded controls from the 'f' stream. */ bool importEmbeddedSiteModels( BinaryInputStream& rInStrm ); /* Final processing of all embedded controls after import. */ - void finalizeEmbeddedControls(); - - /** Moves the control relative to its current position by the passed distance. */ - void moveRelative( const AxPairData& rDistance ); - /** Moves all embedded controls from their relative position in this - control to an absolute position in the parent of this control. */ - void moveEmbeddedToAbsoluteParent(); + void finalizeEmbeddedControls( StorageBase& rStrg ); /** Functor for comparing controls by their tab index. */ static bool compareByTabIndex( const VbaFormControlRef& rxLeft, const VbaFormControlRef& rxRight ); @@ -183,11 +184,12 @@ private: // ============================================================================ -class VbaUserForm : public VbaFormControl, public ControlConverter +class VbaUserForm : public VbaFormControl { public: explicit VbaUserForm( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxGlobalFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& rxDocModel, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr = true ); @@ -202,6 +204,8 @@ public: private: ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxGlobalFactory; + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > mxDocModel; + ControlConverter maConverter; }; // ============================================================================ diff --git a/oox/inc/oox/ole/vbahelper.hxx b/oox/inc/oox/ole/vbahelper.hxx index 8ab2159f5be1..1f67a7759aa6 100644 --- a/oox/inc/oox/ole/vbahelper.hxx +++ b/oox/inc/oox/ole/vbahelper.hxx @@ -55,6 +55,7 @@ const sal_uInt16 VBA_ID_MODULETYPEPROCEDURAL = 0x0021; const sal_uInt16 VBA_ID_PROJECTCODEPAGE = 0x0003; const sal_uInt16 VBA_ID_PROJECTEND = 0x0010; const sal_uInt16 VBA_ID_PROJECTMODULES = 0x000F; +const sal_uInt16 VBA_ID_PROJECTNAME = 0x0004; const sal_uInt16 VBA_ID_PROJECTVERSION = 0x0009; // ============================================================================ diff --git a/oox/inc/oox/ole/vbamodule.hxx b/oox/inc/oox/ole/vbamodule.hxx index 521a5bf5907c..52d04c0e5d45 100644 --- a/oox/inc/oox/ole/vbamodule.hxx +++ b/oox/inc/oox/ole/vbamodule.hxx @@ -69,10 +69,31 @@ public: /** Imports all records for this module until the MODULEEND record. */ void importDirRecords( BinaryInputStream& rDirStrm ); - /** Imports the Basic source code into the passed Basic library. */ - void importSourceCode( + + /** Imports the VBA source code into the passed Basic library. */ + void createAndImportModule( StorageBase& rVbaStrg, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& rxBasicLib, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& rxDocObjectNA, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& rxOleNameOverrides ) const; + /** Creates an empty Basic module in the passed Basic library. */ + void createEmptyModule( + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& rxBasicLib, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& rxDocObjectNA ) const; + +private: + /** Reads and returns the VBA source code from the passed storage. */ + ::rtl::OUString readSourceCode( + StorageBase& rVbaStrg, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& rxOleNameOverrides ) const; + + void extractOleOverrideFromAttr( const rtl::OUString& rAttribute, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& rxOleNameOverrides ) const; + + /** Creates a new Basic module and inserts it into the passed Basic library. */ + void createModule( + const ::rtl::OUString& rVBASourceCode, + const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& rxBasicLib, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& rxDocObjectNA ) const; private: diff --git a/oox/inc/oox/ole/vbaproject.hxx b/oox/inc/oox/ole/vbaproject.hxx index b5bb1dc766fd..fc10e1de3e62 100644 --- a/oox/inc/oox/ole/vbaproject.hxx +++ b/oox/inc/oox/ole/vbaproject.hxx @@ -29,9 +29,9 @@ #ifndef OOX_OLE_VBAPROJECT_HXX #define OOX_OLE_VBAPROJECT_HXX -#include "oox/helper/storagebase.hxx" +#include <map> #include <com/sun/star/uno/XInterface.hpp> -#include "oox/dllapi.h" +#include "oox/helper/storagebase.hxx" namespace com { namespace sun { namespace star { namespace container { class XNameContainer; } @@ -48,7 +48,7 @@ namespace ole { // ============================================================================ -class OOX_DLLPUBLIC VbaFilterConfig +class VbaFilterConfig { public: explicit VbaFilterConfig( @@ -70,7 +70,7 @@ private: // ============================================================================ -class OOX_DLLPUBLIC VbaProject : public VbaFilterConfig +class VbaProject : public VbaFilterConfig { public: explicit VbaProject( @@ -98,6 +98,8 @@ public: /** Returns true, if the document contains the specified dialog. */ bool hasDialog( const ::rtl::OUString& rDialogName ) const; + void setOleOverridesSink( ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& rxOleOverridesSink ){ mxOleOverridesSink = rxOleOverridesSink; } + private: VbaProject( const VbaProject& ); VbaProject& operator=( const VbaProject& ); @@ -115,11 +117,26 @@ private: ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > createDialogLibrary(); /** Imports the VBA code modules and forms. */ - void importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr ); + void importVba( + StorageBase& rVbaPrjStrg, + const GraphicHelper& rGraphicHelper, + bool bDefaultColorBgr ); + /** Copies the entire VBA project storage to the passed document model. */ void copyStorage( StorageBase& rVbaPrjStrg ); + +protected: + /** Registers a dummy module that will be created when the VBA project is + imported. */ + void addDummyModule( const ::rtl::OUString& rName, sal_Int32 nType ); + + /** Called when the import process of the VBA code modules starts. */ + virtual void prepareModuleImport(); + private: + typedef ::std::map< ::rtl::OUString, sal_Int32 > DummyModuleMap; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxGlobalFactory; /// Global service factory. ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > @@ -128,7 +145,10 @@ private: mxBasicLib; /// The Basic library of the document used for import. ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > mxDialogLib; /// The dialog library of the document used for import. - const ::rtl::OUString maLibName; /// Name for Basic and dialog library used for import. + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > + mxOleOverridesSink; + DummyModuleMap maDummyModules; /// Additional empty modules created on import. + ::rtl::OUString maPrjName; /// Name of the VBA project. }; // ============================================================================ diff --git a/oox/inc/oox/xls/drawingfragment.hxx b/oox/inc/oox/xls/drawingfragment.hxx index 7a6de04adca5..71d60433e4c6 100644 --- a/oox/inc/oox/xls/drawingfragment.hxx +++ b/oox/inc/oox/xls/drawingfragment.hxx @@ -32,6 +32,7 @@ #include <com/sun/star/awt/Rectangle.hpp> #include <com/sun/star/awt/Size.hpp> #include "oox/drawingml/shape.hxx" +#include "oox/ole/axcontrol.hxx" #include "oox/vml/vmldrawing.hxx" #include "oox/vml/vmldrawingfragment.hxx" #include "oox/xls/excelhandlers.hxx" @@ -183,6 +184,10 @@ public: virtual void notifyShapeInserted( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& rxShape, const ::com::sun::star::awt::Rectangle& rShapeRect ); + +private: + ::oox::ole::ControlConverter maControlConv; + }; // ============================================================================ diff --git a/oox/inc/oox/xls/excelfilter.hxx b/oox/inc/oox/xls/excelfilter.hxx index 407533f80016..f3e4a571653c 100644 --- a/oox/inc/oox/xls/excelfilter.hxx +++ b/oox/inc/oox/xls/excelfilter.hxx @@ -31,6 +31,7 @@ #include "oox/core/xmlfilterbase.hxx" #include "oox/core/binaryfilterbase.hxx" +#include "oox/ole/vbaprojectfilter.hxx" namespace oox { namespace xls { @@ -97,6 +98,20 @@ private: // ============================================================================ +class ExcelVbaProjectFilter : public ExcelBiffFilter +{ +public: + explicit ExcelVbaProjectFilter( + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxGlobalFactory ); + + virtual bool importDocument() throw(); + +private: + virtual ::rtl::OUString implGetImplementationName() const; +}; + +// ============================================================================ + } // namespace xls } // namespace oox diff --git a/oox/prj/d.lst b/oox/prj/d.lst index 70c7c1ea52ef..c92cf4dd8a90 100644 --- a/oox/prj/d.lst +++ b/oox/prj/d.lst @@ -26,6 +26,7 @@ mkdir: %_DEST%\inc%_EXT%\oox\xls ..\inc\oox\helper\binarystreambase.hxx %_DEST%\inc%_EXT%\oox\helper\binarystreambase.hxx ..\inc\oox\helper\helper.hxx %_DEST%\inc%_EXT%\oox\helper\helper.hxx ..\inc\oox\helper\containerhelper.hxx %_DEST%\inc%_EXT%\oox\helper\containerhelper.hxx +..\inc\oox\helper\graphichelper.hxx %_DEST%\inc%_EXT%\oox\helper\graphichelper.hxx ..\inc\oox\helper\storagebase.hxx %_DEST%\inc%_EXT%\oox\helper\storagebase.hxx ..\inc\oox\helper\zipstorage.hxx %_DEST%\inc%_EXT%\oox\helper\zipstorage.hxx ..\inc\oox\core\filterbase.hxx %_DEST%\inc%_EXT%\oox\core\filterbase.hxx diff --git a/oox/source/core/facreg.cxx b/oox/source/core/facreg.cxx index 590cdd876e93..36dbe9f8ce95 100644 --- a/oox/source/core/facreg.cxx +++ b/oox/source/core/facreg.cxx @@ -61,6 +61,8 @@ namespace oox { namespace xls { SERVICE( BiffDetector ); } namespace xls { SERVICE( ExcelFilter ); } namespace xls { SERVICE( ExcelBiffFilter ); } + namespace xls { SERVICE( ExcelVbaProjectFilter ); } + namespace ole { SERVICE( WordVbaProjectFilter ); } namespace shape { SERVICE( ShapeContextHandler ); } namespace shape { SERVICE( FastTokenHandlerService ); } namespace docprop { SERVICE2( OOXMLDocPropImportImpl ); } @@ -104,6 +106,8 @@ OOX_DLLPUBLIC sal_Bool SAL_CALL component_writeInfo( void * , void * pRegistryKe WRITEINFO( ::oox::xls::BiffDetector ); WRITEINFO( ::oox::xls::ExcelFilter ); WRITEINFO( ::oox::xls::ExcelBiffFilter ); + WRITEINFO( ::oox::xls::ExcelVbaProjectFilter ); + WRITEINFO( ::oox::ole::WordVbaProjectFilter ); WRITEINFO( ::oox::shape::ShapeContextHandler ); WRITEINFO( ::oox::shape::FastTokenHandlerService ); WRITEINFO( ::oox::docprop::OOXMLDocPropImportImpl ); @@ -152,6 +156,8 @@ OOX_DLLPUBLIC void * SAL_CALL component_getFactory( const sal_Char * pImplName, else SINGLEFACTORY( ::oox::xls::BiffDetector ) else SINGLEFACTORY( ::oox::xls::ExcelFilter ) else SINGLEFACTORY( ::oox::xls::ExcelBiffFilter ) + else SINGLEFACTORY( ::oox::xls::ExcelVbaProjectFilter ) + else SINGLEFACTORY( ::oox::ole::WordVbaProjectFilter ) else SINGLEFACTORY( ::oox::shape::ShapeContextHandler) else SINGLEFACTORY( ::oox::shape::FastTokenHandlerService) else SINGLEFACTORY2( ::oox::docprop::OOXMLDocPropImportImpl ) diff --git a/oox/source/ole/axcontrol.cxx b/oox/source/ole/axcontrol.cxx index 58f50cfab78d..bd484dc8d92b 100644 --- a/oox/source/ole/axcontrol.cxx +++ b/oox/source/ole/axcontrol.cxx @@ -27,7 +27,7 @@ ************************************************************************/ #include "oox/ole/axcontrol.hxx" -#include <rtl/tencinfo.h> + #include <com/sun/star/awt/FontSlant.hpp> #include <com/sun/star/awt/FontStrikeout.hpp> #include <com/sun/star/awt/FontUnderline.hpp> @@ -40,42 +40,50 @@ #include <com/sun/star/awt/TextAlign.hpp> #include <com/sun/star/awt/VisualEffect.hpp> #include <com/sun/star/awt/XControlModel.hpp> +#include <com/sun/star/beans/NamedValue.hpp> #include <com/sun/star/container/XIndexContainer.hpp> #include <com/sun/star/form/XForm.hpp> #include <com/sun/star/form/XFormComponent.hpp> #include <com/sun/star/form/XFormsSupplier.hpp> +#include <com/sun/star/form/binding/XBindableValue.hpp> +#include <com/sun/star/form/binding/XListEntrySink.hpp> +#include <com/sun/star/form/binding/XListEntrySource.hpp> +#include <com/sun/star/form/binding/XValueBinding.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/sheet/XCellRangeAddressable.hpp> +#include <com/sun/star/sheet/XCellRangeReferrer.hpp> #include <com/sun/star/style/VerticalAlignment.hpp> -#include "properties.hxx" -#include "tokens.hxx" +#include <com/sun/star/table/CellAddress.hpp> +#include <com/sun/star/table/CellRangeAddress.hpp> +#include <rtl/tencinfo.h> #include "oox/helper/attributelist.hxx" #include "oox/helper/binaryinputstream.hxx" #include "oox/helper/graphichelper.hxx" #include "oox/helper/propertymap.hxx" -#include "oox/helper/propertyset.hxx" - -using ::rtl::OUString; -using ::com::sun::star::awt::Point; -using ::com::sun::star::awt::Size; -using ::com::sun::star::awt::XControlModel; -using ::com::sun::star::container::XIndexContainer; -using ::com::sun::star::container::XNameContainer; -using ::com::sun::star::drawing::XDrawPage; -using ::com::sun::star::form::XForm; -using ::com::sun::star::form::XFormComponent; -using ::com::sun::star::lang::XMultiServiceFactory; -using ::com::sun::star::uno::Any; -using ::com::sun::star::uno::Exception; -using ::com::sun::star::uno::Reference; -using ::com::sun::star::uno::UNO_QUERY; -using ::com::sun::star::uno::UNO_QUERY_THROW; -using ::com::sun::star::uno::UNO_SET_THROW; +#include "properties.hxx" +#include "tokens.hxx" namespace oox { namespace ole { // ============================================================================ +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::form::binding; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::sheet; +using namespace ::com::sun::star::table; +using namespace ::com::sun::star::uno; + +using ::rtl::OUString; + +// ============================================================================ + namespace { const sal_uInt32 COMCTL_ID_SIZE = 0x12344321; @@ -221,14 +229,70 @@ const sal_Int16 API_STATE_UNCHECKED = 0; const sal_Int16 API_STATE_CHECKED = 1; const sal_Int16 API_STATE_DONTKNOW = 2; +// ---------------------------------------------------------------------------- + +/** Tries to extract a range address from a defined name. */ +bool lclExtractRangeFromName( CellRangeAddress& orRangeAddr, const Reference< XModel >& rxDocModel, const OUString& rAddressString ) +{ + try + { + PropertySet aPropSet( rxDocModel ); + Reference< XNameAccess > xRangesNA( aPropSet.getAnyProperty( PROP_NamedRanges ), UNO_QUERY_THROW ); + Reference< XCellRangeReferrer > xReferrer( xRangesNA->getByName( rAddressString ), UNO_QUERY_THROW ); + Reference< XCellRangeAddressable > xAddressable( xReferrer->getReferredCells(), UNO_QUERY_THROW ); + orRangeAddr = xAddressable->getRangeAddress(); + return true; + } + catch( Exception& ) + { + } + return false; +} + +bool lclExtractAddressFromName( CellAddress& orAddress, const Reference< XModel >& rxDocModel, const OUString& rAddressString ) +{ + CellRangeAddress aRangeAddr; + if( lclExtractRangeFromName( aRangeAddr, rxDocModel, rAddressString ) && + (aRangeAddr.StartColumn == aRangeAddr.EndColumn) && + (aRangeAddr.StartRow == aRangeAddr.EndRow) ) + { + orAddress.Sheet = aRangeAddr.Sheet; + orAddress.Column = aRangeAddr.StartColumn; + orAddress.Row = aRangeAddr.StartRow; + return true; + } + return false; +} + +void lclPrepareConverter( PropertySet& rConverter, const Reference< XModel >& rxDocModel, + const OUString& rAddressString, sal_Int32 nRefSheet, bool bRange ) +{ + if( !rConverter.is() ) try + { + Reference< XMultiServiceFactory > xFactory( rxDocModel, UNO_QUERY_THROW ); + OUString aServiceName = bRange ? + CREATE_OUSTRING( "com.sun.star.table.CellRangeAddressConversion" ) : + CREATE_OUSTRING( "com.sun.star.table.CellAddressConversion" ); + rConverter.set( xFactory->createInstance( aServiceName ) ); + } + catch( Exception& ) + { + } + rConverter.setProperty( PROP_XLA1Representation, rAddressString ); + rConverter.setProperty( PROP_ReferenceSheet, nRefSheet ); +} + } // namespace // ============================================================================ -ControlConverter::ControlConverter( const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr ) : +ControlConverter::ControlConverter( const Reference< XModel >& rxDocModel, + const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr ) : + mxDocModel( rxDocModel ), mrGraphicHelper( rGraphicHelper ), mbDefaultColorBgr( bDefaultColorBgr ) { + OSL_ENSURE( mxDocModel.is(), "ControlConverter::ControlConverter - missing document model" ); } ControlConverter::~ControlConverter() @@ -286,6 +350,74 @@ void ControlConverter::convertScrollBar( PropertyMap& rPropMap, rPropMap.setProperty( bAwtModel ? PROP_ScrollValue : PROP_DefaultScrollValue, nPosition ); } +void ControlConverter::bindToSources( const Reference< XControlModel >& rxCtrlModel, + const OUString& rCtrlSource, const OUString& rRowSource, sal_Int32 nRefSheet ) const +{ + // value binding + if( rCtrlSource.getLength() > 0 ) try + { + // first check if the XBindableValue interface is supported + Reference< XBindableValue > xBindable( rxCtrlModel, UNO_QUERY_THROW ); + + // convert address string to cell address struct + CellAddress aAddress; + if( !lclExtractAddressFromName( aAddress, mxDocModel, rCtrlSource ) ) + { + lclPrepareConverter( maAddressConverter, mxDocModel, rCtrlSource, nRefSheet, false ); + if( !maAddressConverter.getProperty( aAddress, PROP_Address ) ) + throw RuntimeException(); + } + + // create argument sequence + NamedValue aValue; + aValue.Name = CREATE_OUSTRING( "BoundCell" ); + aValue.Value <<= aAddress; + Sequence< Any > aArgs( 1 ); + aArgs[ 0 ] <<= aValue; + + // create the CellValueBinding instance and set at the control model + Reference< XMultiServiceFactory > xFactory( mxDocModel, UNO_QUERY_THROW ); + Reference< XValueBinding > xBinding( xFactory->createInstanceWithArguments( + CREATE_OUSTRING( "com.sun.star.table.CellValueBinding" ), aArgs ), UNO_QUERY_THROW ); + xBindable->setValueBinding( xBinding ); + } + catch( Exception& ) + { + } + + // list entry source + if( rRowSource.getLength() > 0 ) try + { + // first check if the XListEntrySink interface is supported + Reference< XListEntrySink > xEntrySink( rxCtrlModel, UNO_QUERY_THROW ); + + // convert address string to cell range address struct + CellRangeAddress aRangeAddr; + if( !lclExtractRangeFromName( aRangeAddr, mxDocModel, rRowSource ) ) + { + lclPrepareConverter( maRangeConverter, mxDocModel, rRowSource, nRefSheet, true ); + if( !maRangeConverter.getProperty( aRangeAddr, PROP_Address ) ) + throw RuntimeException(); + } + + // create argument sequence + NamedValue aValue; + aValue.Name = CREATE_OUSTRING( "CellRange" ); + aValue.Value <<= aRangeAddr; + Sequence< Any > aArgs( 1 ); + aArgs[ 0 ] <<= aValue; + + // create the EntrySource instance and set at the control model + Reference< XMultiServiceFactory > xFactory( mxDocModel, UNO_QUERY_THROW ); + Reference< XListEntrySource > xEntrySource( xFactory->createInstanceWithArguments( + CREATE_OUSTRING( "com.sun.star.table.CellRangeListSource" ), aArgs ), UNO_QUERY_THROW ); + xEntrySink->setListEntrySource( xEntrySource ); + } + catch( Exception& ) + { + } +} + // ActiveX (Forms 2.0) specific conversion ------------------------------------ void ControlConverter::convertAxBackground( PropertyMap& rPropMap, @@ -432,14 +564,16 @@ OUString ControlModelBase::getServiceName() const case API_CONTROL_FIXEDTEXT: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlFixedTextModel" ); case API_CONTROL_IMAGE: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlImageControlModel" ); case API_CONTROL_CHECKBOX: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlCheckBoxModel" ); - case API_CONTROL_RADIOBUTTON: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlRadioButtonModel" ); + case API_CONTROL_RADIOBUTTON: return CREATE_OUSTRING( "com.sun.star.form.component.RadioButton" ); case API_CONTROL_EDIT: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlEditModel" ); - case API_CONTROL_LISTBOX: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlListBoxModel" ); - case API_CONTROL_COMBOBOX: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlComboBoxModel" ); - case API_CONTROL_SPINBUTTON: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlSpinButtonModel" ); - case API_CONTROL_SCROLLBAR: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlScrollBarModel" ); + case API_CONTROL_LISTBOX: return CREATE_OUSTRING( "com.sun.star.form.component.ListBox" ); + case API_CONTROL_COMBOBOX: return CREATE_OUSTRING( "com.sun.star.form.component.ComboBox" ); + case API_CONTROL_SPINBUTTON: return CREATE_OUSTRING( "com.sun.star.form.component.SpinButton" ); + case API_CONTROL_SCROLLBAR: return CREATE_OUSTRING( "com.sun.star.form.component.ScrollBar" ); case API_CONTROL_PROGRESSBAR: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlProgressBarModel" ); - case API_CONTROL_GROUPBOX: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlGroupBoxModel" ); + case API_CONTROL_FRAME: return CREATE_OUSTRING( "com.sun.star.awt.UnoFrameModel" ); + case API_CONTROL_PAGE: return CREATE_OUSTRING( "com.sun.star.awt.UnoPageModel" ); + case API_CONTROL_MULTIPAGE: return CREATE_OUSTRING( "com.sun.star.awt.UnoMultiPageModel" ); case API_CONTROL_DIALOG: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlDialogModel" ); default: OSL_ENSURE( false, "ControlModelBase::getServiceName - no AWT model service supported" ); } @@ -1418,7 +1552,8 @@ ApiControlType AxTabStripModel::getControlType() const void AxTabStripModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const { rPropMap.setProperty( PROP_Decoration, mnTabStyle != AX_TABSTRIP_NONE ); - rPropMap.setProperty( PROP_MultiPageValue, mnSelectedTab ); + // adjust for openoffice ( 1 based ) + rPropMap.setProperty( PROP_MultiPageValue, mnSelectedTab + 1); rConv.convertColor( rPropMap, PROP_BackgroundColor, mnBackColor ); AxFontDataModel::convertProperties( rPropMap, rConv ); } @@ -1542,7 +1677,7 @@ AxFrameModel::AxFrameModel() : ApiControlType AxFrameModel::getControlType() const { - return API_CONTROL_GROUPBOX; + return mbAwtModel ? API_CONTROL_FRAME : API_CONTROL_GROUPBOX; } void AxFrameModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const @@ -1684,10 +1819,10 @@ bool EmbeddedControl::convertProperties( const Reference< XControlModel >& rxCtr // ============================================================================ -EmbeddedForm::EmbeddedForm( const Reference< XMultiServiceFactory >& rxModelFactory, +EmbeddedForm::EmbeddedForm( const Reference< XModel >& rxDocModel, const Reference< XDrawPage >& rxDrawPage, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr ) : - ControlConverter( rGraphicHelper, bDefaultColorBgr ), - mxModelFactory( rxModelFactory ), + ControlConverter( rxDocModel, rGraphicHelper, bDefaultColorBgr ), + mxModelFactory( rxDocModel, UNO_QUERY ), mxFormsSupp( rxDrawPage, UNO_QUERY ) { OSL_ENSURE( mxModelFactory.is(), "EmbeddedForm::EmbeddedForm - missing service factory" ); diff --git a/oox/source/ole/makefile.mk b/oox/source/ole/makefile.mk index 4e01392d4a57..a5232247cfa5 100644 --- a/oox/source/ole/makefile.mk +++ b/oox/source/ole/makefile.mk @@ -51,7 +51,8 @@ SLOFILES = \ $(SLO)$/vbahelper.obj \ $(SLO)$/vbainputstream.obj \ $(SLO)$/vbamodule.obj \ - $(SLO)$/vbaproject.obj + $(SLO)$/vbaproject.obj \ + $(SLO)$/vbaprojectfilter.obj # --- Targets ------------------------------------------------------- diff --git a/oox/source/ole/vbacontrol.cxx b/oox/source/ole/vbacontrol.cxx index 386c1a034641..4a42f7043aaf 100755 --- a/oox/source/ole/vbacontrol.cxx +++ b/oox/source/ole/vbacontrol.cxx @@ -27,17 +27,16 @@ ************************************************************************/ #include "oox/ole/vbacontrol.hxx" + #include <algorithm> #include <set> -#include <rtl/ustrbuf.hxx> #include <com/sun/star/awt/XControlModel.hpp> #include <com/sun/star/container/XNameContainer.hpp> #include <com/sun/star/io/XInputStreamProvider.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> #include <com/sun/star/uno/XComponentContext.hpp> +#include <rtl/ustrbuf.hxx> #include <xmlscript/xmldlg_imexp.hxx> -#include "properties.hxx" -#include "tokens.hxx" #include "oox/helper/attributelist.hxx" #include "oox/helper/binaryinputstream.hxx" #include "oox/helper/propertymap.hxx" @@ -45,26 +44,26 @@ #include "oox/helper/storagebase.hxx" #include "oox/helper/textinputstream.hxx" #include "oox/ole/vbahelper.hxx" - -using ::rtl::OUString; -using ::rtl::OUStringBuffer; -using ::com::sun::star::awt::XControlModel; -using ::com::sun::star::container::XNameContainer; -using ::com::sun::star::io::XInputStreamProvider; -using ::com::sun::star::lang::XMultiServiceFactory; -using ::com::sun::star::uno::Any; -using ::com::sun::star::uno::Exception; -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; +#include "properties.hxx" +#include "tokens.hxx" namespace oox { namespace ole { // ============================================================================ +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +// ============================================================================ + namespace { const sal_uInt16 VBA_SITE_CLASSIDINDEX = 0x8000; @@ -222,17 +221,11 @@ bool VbaSiteModel::importBinaryModel( BinaryInputStream& rInStrm ) aReader.skipUndefinedProperty(); aReader.readStringProperty( maToolTip ); aReader.skipStringProperty(); // license key - aReader.readStringProperty( maLinkedCell ); - aReader.readStringProperty( maSourceRange ); + aReader.readStringProperty( maControlSource ); + aReader.readStringProperty( maRowSource ); return aReader.finalizeImport(); } -void VbaSiteModel::moveRelative( const AxPairData& rDistance ) -{ - maPos.first += rDistance.first; - maPos.second += rDistance.second; -} - bool VbaSiteModel::isVisible() const { return getFlag( mnFlags, VBA_SITE_VISIBLE ); @@ -280,12 +273,12 @@ ControlModelRef VbaSiteModel::createControlModel( const AxClassTable& rClassTabl case VBA_SITE_TEXTBOX: xCtrlModel.reset( new AxTextBoxModel ); break; case VBA_SITE_LISTBOX: xCtrlModel.reset( new AxListBoxModel ); break; case VBA_SITE_COMBOBOX: xCtrlModel.reset( new AxComboBoxModel ); break; - case VBA_SITE_SPINBUTTON: /*xCtrlModel.reset( new AxSpinButtonModel );*/ break; // not supported (?) + case VBA_SITE_SPINBUTTON: xCtrlModel.reset( new AxSpinButtonModel ); break; case VBA_SITE_SCROLLBAR: xCtrlModel.reset( new AxScrollBarModel ); break; - case VBA_SITE_TABSTRIP: break; // not supported + case VBA_SITE_TABSTRIP: xCtrlModel.reset( new AxTabStripModel ); break; case VBA_SITE_FRAME: xCtrlModel.reset( new AxFrameModel ); break; - case VBA_SITE_MULTIPAGE: break; // not supported - case VBA_SITE_FORM: break; // not supported + case VBA_SITE_MULTIPAGE: xCtrlModel.reset( new AxMultiPageModel ); break; + case VBA_SITE_FORM: xCtrlModel.reset( new AxFormPageModel ); break; default: OSL_ENSURE( false, "VbaSiteModel::createControlModel - unknown type index" ); } } @@ -339,6 +332,11 @@ void VbaSiteModel::convertProperties( PropertyMap& rPropMap, } } +void VbaSiteModel::bindToSources( const Reference< XControlModel >& rxCtrlModel, const ControlConverter& rConv ) const +{ + rConv.bindToSources( rxCtrlModel, maControlSource, maRowSource ); +} + // ============================================================================ VbaFormControl::VbaFormControl() @@ -445,11 +443,9 @@ void VbaFormControl::importStorage( StorageBase& rStrg, const AxClassTable& rCla maControls.forEachMem( &VbaFormControl::importModelOrStorage, ::boost::ref( aOStrm ), ::boost::ref( rStrg ), ::boost::cref( maClassTable ) ); - /* Reorder the controls (sorts all option buttons of an option - group together), and move all children of all embedded frames - (group boxes) to this control (UNO group boxes cannot contain - other controls). */ - finalizeEmbeddedControls(); + /** Final processing on the control and all embedded controls, + depending on the type of this control. */ + finalizeEmbeddedControls( rStrg ); } } } @@ -471,6 +467,9 @@ bool VbaFormControl::convertProperties( const Reference< XControlModel >& rxCtrl PropertySet aPropSet( rxCtrlModel ); aPropSet.setProperties( aPropMap ); + // bind to control source and row source range + mxSiteModel->bindToSources( rxCtrlModel, rConv ); + // create and convert all embedded controls if( !maControls.empty() ) try { @@ -553,138 +552,182 @@ bool VbaFormControl::importEmbeddedSiteModels( BinaryInputStream& rInStrm ) return bValid; } -void VbaFormControl::finalizeEmbeddedControls() -{ - /* This function performs two tasks: - - 1) Reorder the controls appropriately (sort all option buttons of an - option group together to make grouping work). - 2) Move all children of all embedded frames (group boxes) to this - control (UNO group boxes cannot contain other controls). - */ - - // first, sort all controls by original tab index - ::std::sort( maControls.begin(), maControls.end(), &compareByTabIndex ); - - /* Collect the programmatical names of all embedded controls (needed to be - able to set unused names to new dummy controls created below). Also - collect the names of all children of embedded frames (group boxes). - Luckily, names of controls must be unique in the entire form, not just - in the current container. */ - VbaControlNamesSet aControlNames; - VbaControlNameInserter aInserter( aControlNames ); - maControls.forEach( aInserter ); - for( VbaFormControlVector::iterator aIt = maControls.begin(), aEnd = maControls.end(); aIt != aEnd; ++aIt ) - if( (*aIt)->mxCtrlModel.get() && ((*aIt)->mxCtrlModel->getControlType() == API_CONTROL_GROUPBOX) ) - (*aIt)->maControls.forEach( aInserter ); - - /* Reprocess the sorted list and collect all option button controls that - are part of the same option group (determined by group name). All - controls will be stored in a vector of vectors, that collects every - option button group in one vector element, and other controls between - these option groups (or leading or trailing controls) in other vector - elements. If an option button group follows another group, a dummy - separator control has to be inserted. */ - typedef RefVector< VbaFormControlVector > VbaFormControlVectorVector; - VbaFormControlVectorVector aControlGroups; - - typedef RefMap< OUString, VbaFormControlVector > VbaFormControlVectorMap; - VbaFormControlVectorMap aOptionGroups; - - typedef VbaFormControlVectorMap::mapped_type VbaFormControlVectorRef; - bool bLastWasOptionButton = false; - for( VbaFormControlVector::iterator aIt = maControls.begin(), aEnd = maControls.end(); aIt != aEnd; ++aIt ) +void VbaFormControl::finalizeEmbeddedControls( StorageBase& rStrg ) +{ + /* Store all embedded controls in a temporary vector, so "exit on error" + will leave this control empty. */ + VbaFormControlVector aControls; + aControls.swap( maControls ); + + /* If this is a multipage control, it stores additional data in the 'x' + stream of its storage. It contains the control identifiers of the form + page controls that contain the embedded controls of each page. + Additionally, the order of these pages is stored there (they are not + nessecarily in the order they are persisted in). */ + if( AxMultiPageModel* pMultiPageModel = dynamic_cast< AxMultiPageModel* >( mxCtrlModel.get() ) ) { - VbaFormControlRef xControl = *aIt; - const ControlModelBase* pCtrlModel = xControl->mxCtrlModel.get(); + // read additional attributes from the 'x' stream + BinaryXInputStream aXStrm( rStrg.openInputStream( CREATE_OUSTRING( "x" ) ), true ); + OSL_ENSURE( !aXStrm.isEof(), "VbaFormControl::finalizeEmbeddedControls - missing 'x' stream" ); + if( aXStrm.isEof() ) return; - if( const AxOptionButtonModel* pOptButtonModel = dynamic_cast< const AxOptionButtonModel* >( pCtrlModel ) ) + // skip the page property structures related to all controls + for( size_t nSiteIdx = 0, nSiteCount = aControls.size(); nSiteIdx < nSiteCount; ++nSiteIdx ) { - // check if a new option group needs to be created - const OUString& rGroupName = pOptButtonModel->getGroupName(); - VbaFormControlVectorRef& rxOptionGroup = aOptionGroups[ rGroupName ]; - if( !rxOptionGroup ) - { - /* If last control was an option button too, we have two - option groups following each other, so a dummy separator - control is needed. */ - if( bLastWasOptionButton ) - { - VbaFormControlVectorRef xDummyGroup( new VbaFormControlVector ); - aControlGroups.push_back( xDummyGroup ); - OUString aName = aControlNames.generateDummyName(); - VbaFormControlRef xDummyControl( new VbaDummyFormControl( aName ) ); - xDummyGroup->push_back( xDummyControl ); - } - rxOptionGroup.reset( new VbaFormControlVector ); - aControlGroups.push_back( rxOptionGroup ); - } - /* Append the option button to the control group (which is now - referred by the vector aControlGroups and by the map - aOptionGroups). */ - rxOptionGroup->push_back( xControl ); - bLastWasOptionButton = true; + AxBinaryPropertyReader aReader( aXStrm ); + aReader.skipUndefinedProperty(); + aReader.skipIntProperty< sal_uInt32 >(); // transition effect + aReader.skipIntProperty< sal_uInt32 >(); // transition period + if( !aReader.finalizeImport() ) return; } - else - { - // open a new control group, if the last group is an option group - if( bLastWasOptionButton || aControlGroups.empty() ) - { - VbaFormControlVectorRef xControlGroup( new VbaFormControlVector ); - aControlGroups.push_back( xControlGroup ); - } - // append the control to the last control group - VbaFormControlVector& rLastGroup = *aControlGroups.back(); - rLastGroup.push_back( xControl ); - bLastWasOptionButton = false; - // if control is a group box, move all its children to this control - if( pCtrlModel && (pCtrlModel->getControlType() == API_CONTROL_GROUPBOX) ) + // read the multipage property structure containing a list of page IDs + sal_Int32 nPageCount = 0; + sal_Int32 nTabStripId = 0; + AxBinaryPropertyReader aReader( aXStrm ); + aReader.skipUndefinedProperty(); + aReader.readIntProperty< sal_Int32 >( nPageCount ); + aReader.readIntProperty< sal_Int32 >( nTabStripId ); + if( !aReader.finalizeImport() ) return; + // read the array containing all page identifiers in current order + typedef ::std::vector< sal_Int32 > AxPageIdVector; + AxPageIdVector aPageIds; + for( sal_Int32 nPage = 0; !aXStrm.isEof() && (nPage < nPageCount); ++nPage ) + aPageIds.push_back( aXStrm.readInt32() ); + if( aXStrm.isEof() ) return; + + // check the page count value + bool bValidPageCount = (0 < nPageCount) && (static_cast< size_t >( nPageCount + 1 ) == aControls.size()); + OSL_ENSURE( bValidPageCount, "VbaFormControl::finalizeEmbeddedControls - invalid number of pages" ); + if( !bValidPageCount ) return; + + /* Check that this multipage contains the expected controls: + - a tabstrip control, specified by nTabStripId, + - form page controls (containing the embedded controls of each page). */ + + // the controls may be in arbitrary order, first map them by ID + RefMap< sal_Int32, VbaFormControl > aControlsById; + for( VbaFormControlVector::iterator aIt = aControls.begin(), aEnd = aControls.end(); aIt != aEnd; ++aIt ) + { + VbaFormControlRef xControl = *aIt; + sal_Int32 nId = xControl->getControlId(); + OSL_ENSURE( (nId > 0) && !aControlsById.has( nId ), "VbaFormControl::finalizeEmbeddedControls - invalid control ID" ); + aControlsById[ nId ] = xControl; + } + // store tabstrip in the multipage, it will care about property conversion + AxTabStripModelRef xTabStripModel; + VbaFormControlRef xControl = aControlsById.get( nTabStripId ); + if( xControl.get() ) + xTabStripModel = ::boost::dynamic_pointer_cast< AxTabStripModel >( xControl->mxCtrlModel ); + OSL_ENSURE( xTabStripModel.get(), "VbaFormControl::finalizeEmbeddedControls - missing tabstrip control" ); + if( !xTabStripModel ) return; + pMultiPageModel->setTabStripModel( xTabStripModel ); + aControlsById.erase( nTabStripId ); + // store all pages in maControls in the correct order specified by aPageIds + sal_Int32 nTabIndex = 0; + for( AxPageIdVector::iterator aIt = aPageIds.begin(), aEnd = aPageIds.end(); aIt != aEnd; ++aIt, ++nTabIndex ) + { + VbaFormControlRef rControl = aControlsById.get( *aIt ); + AxFormPageModel* pFormPageModel = rControl.get() ? dynamic_cast< AxFormPageModel* >( rControl->mxCtrlModel.get() ) : 0; + OSL_ENSURE( pFormPageModel, "VbaFormControl::finalizeEmbeddedControls - missing formpage control" ); + // do not exit on error but try to collect as much pages as possible + if( pFormPageModel ) { - /* Move all embedded controls of the group box relative to the - position of the group box. */ - xControl->moveEmbeddedToAbsoluteParent(); - /* Insert all children of the group box into the last control - group (following the group box). */ - rLastGroup.insert( rLastGroup.end(), xControl->maControls.begin(), xControl->maControls.end() ); - xControl->maControls.clear(); - // check if last control of the group box is an option button - bLastWasOptionButton = dynamic_cast< const AxOptionButtonModel* >( rLastGroup.back()->mxCtrlModel.get() ) != 0; + // get the tab caption from tabstrip control and set it at the formpage + OUString aCaption = xTabStripModel->getCaption( nTabIndex ); + pFormPageModel->importProperty( XML_Caption, aCaption ); + // store the control in maControls + maControls.push_back( rControl ); + aControlsById.erase( *aIt ); } } } - - // flatten the vector of vectors of form controls to a single vector - maControls.clear(); - for( VbaFormControlVectorVector::iterator aIt = aControlGroups.begin(), aEnd = aControlGroups.end(); aIt != aEnd; ++aIt ) - maControls.insert( maControls.end(), (*aIt)->begin(), (*aIt)->end() ); -} - -void VbaFormControl::moveRelative( const AxPairData& rDistance ) -{ - if( mxSiteModel.get() ) - mxSiteModel->moveRelative( rDistance ); -} - -void VbaFormControl::moveEmbeddedToAbsoluteParent() -{ - if( mxSiteModel.get() && !maControls.empty() ) + else { - // distance to move is equal to position of this control in its parent - AxPairData aDistance = mxSiteModel->getPosition(); - - /* For group boxes: add half of the font height to Y position (VBA - positions relative to frame border line, not to 'top' of frame). */ - const AxFontDataModel* pFontModel = dynamic_cast< const AxFontDataModel* >( mxCtrlModel.get() ); - if( pFontModel && (pFontModel->getControlType() == API_CONTROL_GROUPBOX) ) + /* Reorder the controls appropriately (sort all option buttons of an + option group together to make grouping work), and erase all plain + tabstrip controls (currently not supported in UNO dialogs). */ + + // first, sort all controls by original tab index + ::std::sort( aControls.begin(), aControls.end(), &compareByTabIndex ); + + /* Collect the programmatical names of all embedded controls (needed to be + able to set unused names to new dummy controls created below). */ + VbaControlNamesSet aControlNames; + VbaControlNameInserter aInserter( aControlNames ); + aControls.forEach( aInserter ); + + /* Reprocess the sorted list and collect all option button controls that + are part of the same option group (determined by group name). All + controls will be stored in a vector of vectors, that collects every + option button group in one vector element, and other controls between + these option groups (or leading or trailing controls) in other vector + elements. If an option button group follows another group, a dummy + separator control has to be inserted. */ + typedef RefVector< VbaFormControlVector > VbaFormControlVectorVector; + VbaFormControlVectorVector aControlGroups; + + typedef RefMap< OUString, VbaFormControlVector > VbaFormControlVectorMap; + VbaFormControlVectorMap aOptionGroups; + + typedef VbaFormControlVectorMap::mapped_type VbaFormControlVectorRef; + bool bLastWasOptionButton = false; + for( VbaFormControlVector::iterator aIt = aControls.begin(), aEnd = aControls.end(); aIt != aEnd; ++aIt ) { - // convert points to 1/100 mm (1 pt = 1/72 inch = 2.54/72 cm = 2540/72 1/100 mm) - sal_Int32 nFontHeight = static_cast< sal_Int32 >( pFontModel->getFontHeight() * 2540 / 72 ); - aDistance.second += nFontHeight / 2; + VbaFormControlRef xControl = *aIt; + const ControlModelBase* pCtrlModel = xControl->mxCtrlModel.get(); + if ( !pCtrlModel ) // skip unsupported controls + continue; + if( const AxOptionButtonModel* pOptButtonModel = dynamic_cast< const AxOptionButtonModel* >( pCtrlModel ) ) + { + // check if a new option group needs to be created + const OUString& rGroupName = pOptButtonModel->getGroupName(); + VbaFormControlVectorRef& rxOptionGroup = aOptionGroups[ rGroupName ]; + if( !rxOptionGroup ) + { + /* If last control was an option button too, we have two + option groups following each other, so a dummy separator + control is needed. */ + if( bLastWasOptionButton ) + { + VbaFormControlVectorRef xDummyGroup( new VbaFormControlVector ); + aControlGroups.push_back( xDummyGroup ); + OUString aName = aControlNames.generateDummyName(); + VbaFormControlRef xDummyControl( new VbaDummyFormControl( aName ) ); + xDummyGroup->push_back( xDummyControl ); + } + rxOptionGroup.reset( new VbaFormControlVector ); + aControlGroups.push_back( rxOptionGroup ); + } + /* Append the option button to the control group (which is now + referred by the vector aControlGroups and by the map + aOptionGroups). */ + rxOptionGroup->push_back( xControl ); + bLastWasOptionButton = true; + } + else + { + // skip unsupported controls (tabstrips and page controls) + ApiControlType eCtrlType = pCtrlModel->getControlType(); + if( (eCtrlType != API_CONTROL_TABSTRIP) && (eCtrlType != API_CONTROL_PAGE) ) + { + // open a new control group, if the last group is an option group + if( bLastWasOptionButton || aControlGroups.empty() ) + { + VbaFormControlVectorRef xControlGroup( new VbaFormControlVector ); + aControlGroups.push_back( xControlGroup ); + } + // append the control to the last control group + VbaFormControlVector& rLastGroup = *aControlGroups.back(); + rLastGroup.push_back( xControl ); + bLastWasOptionButton = false; + } + } } - // move the embedded controls - maControls.forEachMem( &VbaFormControl::moveRelative, ::boost::cref( aDistance ) ); + // flatten the vector of vectors of form controls to a single vector + for( VbaFormControlVectorVector::iterator aIt = aControlGroups.begin(), aEnd = aControlGroups.end(); aIt != aEnd; ++aIt ) + maControls.insert( maControls.end(), (*aIt)->begin(), (*aIt)->end() ); } } @@ -753,9 +796,10 @@ bool lclEatKeyword( OUString& rCodeLine, const OUString& rKeyword ) // ---------------------------------------------------------------------------- VbaUserForm::VbaUserForm( const Reference< XMultiServiceFactory >& rxGlobalFactory, - const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr ) : - ControlConverter( rGraphicHelper, bDefaultColorBgr ), - mxGlobalFactory( rxGlobalFactory ) + const Reference< XModel >& rxDocModel, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr ) : + mxGlobalFactory( rxGlobalFactory ), + mxDocModel( rxDocModel ), + maConverter( rxDocModel, rGraphicHelper, bDefaultColorBgr ) { OSL_ENSURE( mxGlobalFactory.is(), "VbaUserForm::VbaUserForm - missing service factory" ); } @@ -764,7 +808,7 @@ void VbaUserForm::importForm( const Reference< XModel >& rxDocModel, const Refer StorageBase& rVbaFormStrg, const OUString& rModuleName, rtl_TextEncoding eTextEnc ) { OSL_ENSURE( rxDialogLib.is(), "VbaUserForm::importForm - missing dialog library" ); - if( !mxGlobalFactory.is() || !rxDialogLib.is() ) + if( !mxGlobalFactory.is() || !mxDocModel.is() || !rxDialogLib.is() ) return; // check that the '03VBFrame' stream exists, this is required for forms @@ -826,7 +870,7 @@ void VbaUserForm::importForm( const Reference< XModel >& rxDocModel, const Refer Reference< XNameContainer > xDialogNC( xDialogModel, UNO_QUERY_THROW ); // convert properties and embedded controls - if( convertProperties( xDialogModel, *this, 0 ) ) + if( convertProperties( xDialogModel, maConverter, 0 ) ) { // export the dialog to XML and insert it into the dialog library PropertySet aFactoryProps( mxGlobalFactory ); diff --git a/oox/source/ole/vbamodule.cxx b/oox/source/ole/vbamodule.cxx index d8c528b1bfc0..310f86572ce8 100644 --- a/oox/source/ole/vbamodule.cxx +++ b/oox/source/ole/vbamodule.cxx @@ -27,29 +27,101 @@ ************************************************************************/ #include "oox/ole/vbamodule.hxx" +#include <hash_map> #include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> #include <com/sun/star/script/ModuleInfo.hpp> #include <com/sun/star/script/ModuleType.hpp> #include <com/sun/star/script/vba/XVBAModuleInfo.hpp> +#include <cppuhelper/implbase1.hxx> #include "oox/helper/binaryinputstream.hxx" #include "oox/helper/storagebase.hxx" #include "oox/helper/textinputstream.hxx" #include "oox/ole/vbahelper.hxx" #include "oox/ole/vbainputstream.hxx" -using ::rtl::OUString; -using ::rtl::OUStringBuffer; +namespace oox { +namespace ole { + +// ============================================================================ using namespace ::com::sun::star::container; using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; using namespace ::com::sun::star::script; using namespace ::com::sun::star::script::vba; using namespace ::com::sun::star::uno; -namespace oox { -namespace ole { - +using ::rtl::OUString; +using ::rtl::OUStringBuffer; // ============================================================================ +typedef ::cppu::WeakImplHelper1< XIndexContainer > OleIdToNameContainer_BASE; +typedef std::hash_map< sal_Int32, rtl::OUString > ObjIdToName; + +class OleIdToNameContainer : public OleIdToNameContainer_BASE +{ + ObjIdToName ObjIdToNameHash; + ::osl::Mutex m_aMutex; + bool hasByIndex( ::sal_Int32 Index ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + return ( ObjIdToNameHash.find( Index ) != ObjIdToNameHash.end() ); + } +public: + OleIdToNameContainer() {} + // XIndexContainer Methods + virtual void SAL_CALL insertByIndex( ::sal_Int32 Index, const Any& Element ) throw (IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + rtl::OUString sOleName; + if ( !( Element >>= sOleName ) ) + throw IllegalArgumentException(); + ObjIdToNameHash[ Index ] = sOleName; + } + virtual void SAL_CALL removeByIndex( ::sal_Int32 Index ) throw (IndexOutOfBoundsException, WrappedTargetException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !hasByIndex( Index ) ) + throw IndexOutOfBoundsException(); + ObjIdToNameHash.erase( ObjIdToNameHash.find( Index ) ); + } + // XIndexReplace Methods + virtual void SAL_CALL replaceByIndex( ::sal_Int32 Index, const Any& Element ) throw (IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !hasByIndex( Index ) ) + throw IndexOutOfBoundsException(); + rtl::OUString sOleName; + if ( !( Element >>= sOleName ) ) + throw IllegalArgumentException(); + ObjIdToNameHash[ Index ] = sOleName; + } + // XIndexAccess Methods + virtual ::sal_Int32 SAL_CALL getCount( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + return ObjIdToNameHash.size(); + } + virtual Any SAL_CALL getByIndex( ::sal_Int32 Index ) throw (IndexOutOfBoundsException, WrappedTargetException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !hasByIndex( Index ) ) + throw IndexOutOfBoundsException(); + return makeAny( ObjIdToNameHash[ Index ] ); + } + // XElementAccess Methods + virtual Type SAL_CALL getElementType( ) throw (RuntimeException) + { + return ::getCppuType( static_cast< const ::rtl::OUString* >( 0 ) ); + } + virtual ::sal_Bool SAL_CALL hasElements( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + return ( getCount() > 0 ); + } +}; + + // ============================================================================ VbaModule::VbaModule( const Reference< XModel >& rxDocModel, const OUString& rName, rtl_TextEncoding eTextEnc, bool bExecutable ) : mxDocModel( rxDocModel ), @@ -129,18 +201,86 @@ void VbaModule::importDirRecords( BinaryInputStream& rDirStrm ) OSL_ENSURE( mnOffset < SAL_MAX_UINT32, "VbaModule::importDirRecords - missing module stream offset" ); } -void VbaModule::importSourceCode( StorageBase& rVbaStrg, - const Reference< XNameContainer >& rxBasicLib, const Reference< XNameAccess >& rxDocObjectNA ) const +void VbaModule::createAndImportModule( StorageBase& rVbaStrg, const Reference< XNameContainer >& rxBasicLib, + const Reference< XNameAccess >& rxDocObjectNA, const Reference< XNameContainer >& rxOleNameOverrides ) const { - if( (maName.getLength() == 0) || (maStreamName.getLength() == 0) || (mnOffset == SAL_MAX_UINT32) ) - return; + OUString aVBASourceCode = readSourceCode( rVbaStrg, rxOleNameOverrides ); + createModule( aVBASourceCode, rxBasicLib, rxDocObjectNA ); +} + +void VbaModule::createEmptyModule( const Reference< XNameContainer >& rxBasicLib, const Reference< XNameAccess >& rxDocObjectNA ) const +{ + createModule( OUString(), rxBasicLib, rxDocObjectNA ); +} - BinaryXInputStream aInStrm( rVbaStrg.openInputStream( maStreamName ), true ); - OSL_ENSURE( !aInStrm.isEof(), "VbaModule::importSourceCode - cannot open module stream" ); - // skip the 'performance cache' stored before the actual source code - aInStrm.seek( mnOffset ); - // if stream is still valid, load the source code - if( aInStrm.isEof() ) +// private -------------------------------------------------------------------- + +OUString VbaModule::readSourceCode( StorageBase& rVbaStrg, const Reference< XNameContainer >& rxOleNameOverrides ) const +{ + OUStringBuffer aSourceCode; + if( (maStreamName.getLength() > 0) && (mnOffset != SAL_MAX_UINT32) ) + { + BinaryXInputStream aInStrm( rVbaStrg.openInputStream( maStreamName ), true ); + OSL_ENSURE( !aInStrm.isEof(), "VbaModule::readSourceCode - cannot open module stream" ); + // skip the 'performance cache' stored before the actual source code + aInStrm.seek( mnOffset ); + // if stream is still valid, load the source code + if( !aInStrm.isEof() ) + { + // decompression starts at current stream position of aInStrm + VbaInputStream aVbaStrm( aInStrm ); + // load the source code line-by-line, with some more processing + TextInputStream aVbaTextStrm( aVbaStrm, meTextEnc ); + while( !aVbaTextStrm.isEof() ) + { + OUString aCodeLine = aVbaTextStrm.readLine(); + if( aCodeLine.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "Attribute " ) ) ) + { + // attribute + extractOleOverrideFromAttr( aCodeLine, rxOleNameOverrides ); + } + else + { + // normal source code line + if( !mbExecutable ) + aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Rem " ) ); + aSourceCode.append( aCodeLine ).append( sal_Unicode( '\n' ) ); + } + } + } + } + return aSourceCode.makeStringAndClear(); +} + +void VbaModule::extractOleOverrideFromAttr( const OUString& rAttribute, const Reference< XNameContainer >& rxOleNameOverrides ) const +{ + // 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" + OUString sControlAttribute = CREATE_OUSTRING( "Attribute VB_Control = \"" ); + if ( rxOleNameOverrides.is() && rAttribute.indexOf( sControlAttribute ) != -1 ) + { + OUString sRest = rAttribute.copy( sControlAttribute.getLength() ); + sal_Int32 nPos = sRest.indexOf( ',' ); + OUString sCntrlName = sRest.copy( 0, nPos ); + + sal_Int32 nCntrlId = sRest.copy( nPos + 1 ).copy( 0, sRest.indexOf( ',', nPos + 1) ).toInt32(); + OSL_TRACE("In module %s, assiging %d controlname %s", + rtl::OUStringToOString( maName, RTL_TEXTENCODING_UTF8 ).getStr(), nCntrlId, + rtl::OUStringToOString( sCntrlName, RTL_TEXTENCODING_UTF8 ).getStr() ); + if ( !rxOleNameOverrides->hasByName( maName ) ) + rxOleNameOverrides->insertByName( maName, Any( Reference< XIndexContainer> ( new OleIdToNameContainer ) ) ); + Reference< XIndexContainer > xIdToOleName; + if ( rxOleNameOverrides->getByName( maName ) >>= xIdToOleName ) + xIdToOleName->insertByIndex( nCntrlId, makeAny( sCntrlName ) ); + } +} + +void VbaModule::createModule( const OUString& rVBASourceCode, + const Reference< XNameContainer >& rxBasicLib, const Reference< XNameAccess >& rxDocObjectNA ) const +{ + if( maName.getLength() == 0 ) return; // prepare the Basic module @@ -189,21 +329,8 @@ void VbaModule::importSourceCode( StorageBase& rVbaStrg, append( maName.replace( ' ', '_' ) ).append( sal_Unicode( '\n' ) ); } - // decompression starts at current stream position of aInStrm - VbaInputStream aVbaStrm( aInStrm ); - // load the source code line-by-line, with some more processing - TextInputStream aVbaTextStrm( aVbaStrm, meTextEnc ); - while( !aVbaTextStrm.isEof() ) - { - OUString aCodeLine = aVbaTextStrm.readLine(); - // skip all 'Attribute' statements - if( !aCodeLine.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "Attribute " ) ) ) - { - if( !mbExecutable ) - aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Rem " ) ); - aSourceCode.append( aCodeLine ).append( sal_Unicode( '\n' ) ); - } - } + // append passed VBA source code + aSourceCode.append( rVBASourceCode ); // close the subroutine named after the module if( !mbExecutable ) @@ -226,7 +353,7 @@ void VbaModule::importSourceCode( StorageBase& rVbaStrg, } catch( Exception& ) { - OSL_ENSURE( false, "VbaModule::importSourceCode - cannot insert module into library" ); + OSL_ENSURE( false, "VbaModule::createModule - cannot insert module into library" ); } } diff --git a/oox/source/ole/vbaproject.cxx b/oox/source/ole/vbaproject.cxx index fad2dba04ffa..f8acf017135b 100755 --- a/oox/source/ole/vbaproject.cxx +++ b/oox/source/ole/vbaproject.cxx @@ -130,11 +130,9 @@ VbaProject::VbaProject( const Reference< XMultiServiceFactory >& rxGlobalFactory VbaFilterConfig( rxGlobalFactory, rConfigCompName ), mxGlobalFactory( rxGlobalFactory ), mxDocModel( rxDocModel ), - maLibName( CREATE_OUSTRING( "Standard" ) ) + maPrjName( CREATE_OUSTRING( "Standard" ) ) { OSL_ENSURE( mxDocModel.is(), "VbaProject::VbaProject - missing document model" ); - mxBasicLib = openLibrary( PROP_BasicLibraries, false ); - mxDialogLib = openLibrary( PROP_DialogLibraries, false ); } VbaProject::~VbaProject() @@ -174,6 +172,18 @@ bool VbaProject::hasDialog( const OUString& rDialogName ) const return mxDialogLib.is() && mxDialogLib->hasByName( rDialogName ); } +// protected ------------------------------------------------------------------ + +void VbaProject::addDummyModule( const OUString& rName, sal_Int32 nType ) +{ + OSL_ENSURE( rName.getLength() > 0, "VbaProject::addDummyModule - missing module name" ); + maDummyModules[ rName ] = nType; +} + +void VbaProject::prepareModuleImport() +{ +} + // private -------------------------------------------------------------------- Reference< XLibraryContainer > VbaProject::getLibraryContainer( sal_Int32 nPropId ) @@ -189,9 +199,9 @@ Reference< XNameContainer > VbaProject::openLibrary( sal_Int32 nPropId, bool bCr try { Reference< XLibraryContainer > xLibContainer( getLibraryContainer( nPropId ), UNO_SET_THROW ); - if( bCreateMissing && !xLibContainer->hasByName( maLibName ) ) - xLibContainer->createLibrary( maLibName ); - xLibrary.set( xLibContainer->getByName( maLibName ), UNO_QUERY_THROW ); + if( bCreateMissing && !xLibContainer->hasByName( maPrjName ) ) + xLibContainer->createLibrary( maPrjName ); + xLibrary.set( xLibContainer->getByName( maPrjName ), UNO_QUERY_THROW ); } catch( Exception& ) { @@ -232,6 +242,9 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap if( aDirStrm.isEof() ) return; + // virtual call, derived classes may do some preparations + prepareModuleImport(); + // read all records of the directory rtl_TextEncoding eTextEnc = RTL_TEXTENCODING_MS_1252; sal_uInt16 nModuleCount = 0; @@ -260,6 +273,14 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap eTextEnc = eNewTextEnc; } break; + case VBA_ID_PROJECTNAME: + { + OUString aPrjName = aRecStrm.readCharArrayUC( nRecSize, eTextEnc ); + OSL_ENSURE( aPrjName.getLength() > 0, "VbaProject::importVba - invalid project name" ); + if( aPrjName.getLength() > 0 ) + maPrjName = aPrjName; + } + break; case VBA_ID_PROJECTMODULES: OOX_ENSURE_RECORDSIZE( nRecSize == 2 ); OSL_ENSURE( aModules.empty(), "VbaProject::importVba - unexpected PROJECTMODULES record" ); @@ -346,11 +367,21 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap } } + // create empty dummy modules + VbaModuleMap aDummyModules; + for( DummyModuleMap::iterator aIt = maDummyModules.begin(), aEnd = maDummyModules.end(); aIt != aEnd; ++aIt ) + { + OSL_ENSURE( !aModules.has( aIt->first ) && !aDummyModules.has( aIt->first ), "VbaProject::importVba - multiple modules with the same name" ); + VbaModuleMap::mapped_type& rxModule = aDummyModules[ aIt->first ]; + rxModule.reset( new VbaModule( mxDocModel, aIt->first, eTextEnc, bExecutable ) ); + rxModule->setType( aIt->second ); + } + /* Now it is time to load the source code. All modules will be inserted - into the Basic library of the document specified by the 'maLibName' + into the Basic library of the document specified by the 'maPrjName' member. Do not create the Basic library, if there are no modules specified. */ - if( !aModules.empty() ) try + if( !aModules.empty() || !aDummyModules.empty() ) try { // get the model factory and the basic library Reference< XMultiServiceFactory > xModelFactory( mxDocModel, UNO_QUERY_THROW ); @@ -359,7 +390,10 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap // set library container to VBA compatibility mode try { - Reference< XVBACompatibility >( getLibraryContainer( PROP_BasicLibraries ), UNO_QUERY_THROW )->setVBACompatibilityMode( sal_True ); + Reference< XVBACompatibility > xVBACompat( getLibraryContainer( PROP_BasicLibraries ), UNO_QUERY_THROW ); + xVBACompat->setVBACompatibilityMode( sal_True ); + xVBACompat->setProjectName( maPrjName ); + } catch( Exception& ) { @@ -385,10 +419,17 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap // not all documents support this } - // call Basic source code import for each module, boost::[c]ref enforces pass-by-ref if( xBasicLib.is() ) - aModules.forEachMem( &VbaModule::importSourceCode, - ::boost::ref( *xVbaStrg ), ::boost::cref( xBasicLib ), ::boost::cref( xDocObjectNA ) ); + { + // call Basic source code import for each module, boost::[c]ref enforces pass-by-ref + aModules.forEachMem( &VbaModule::createAndImportModule, + ::boost::ref( *xVbaStrg ), ::boost::cref( xBasicLib ), + ::boost::cref( xDocObjectNA ), ::boost::cref( mxOleOverridesSink ) ); + + // create empty dummy modules + aDummyModules.forEachMem( &VbaModule::createEmptyModule, + ::boost::cref( xBasicLib ), ::boost::cref( xDocObjectNA ) ); + } } catch( Exception& ) { @@ -418,7 +459,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 ); + VbaUserForm aForm( mxGlobalFactory, mxDocModel, rGraphicHelper, bDefaultColorBgr ); aForm.importForm( mxDocModel, xDialogLib, *xSubStrg, aModuleName, eTextEnc ); } catch( Exception& ) diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt index 98f712fbedc6..e8c33b4fc71a 100644 --- a/oox/source/token/properties.txt +++ b/oox/source/token/properties.txt @@ -6,6 +6,7 @@ Adjust AdjustContrast AdjustLuminance AdjustmentValues +Address Align AnchorPosition ArrangeOrder @@ -334,6 +335,7 @@ RefX RefY Reference ReferenceDevice +ReferenceSheet RegularExpressions RelId RelativeHorizontalTabbarWidth @@ -463,5 +465,6 @@ Weight WhiteDay Width WritingMode +XLA1Representation ZoomType ZoomValue diff --git a/oox/source/token/tokenmap.cxx b/oox/source/token/tokenmap.cxx index d02a74807ec1..c62fe2277b52 100644 --- a/oox/source/token/tokenmap.cxx +++ b/oox/source/token/tokenmap.cxx @@ -33,8 +33,6 @@ #include "tokens.hxx" #include "oox/helper/containerhelper.hxx" -#include <string.h> - using ::rtl::OString; using ::rtl::OUString; using ::com::sun::star::uno::Sequence; diff --git a/oox/source/vml/vmldrawing.cxx b/oox/source/vml/vmldrawing.cxx index 1e3bd0135b5e..61dfd4b6c362 100644 --- a/oox/source/vml/vmldrawing.cxx +++ b/oox/source/vml/vmldrawing.cxx @@ -103,7 +103,7 @@ Drawing::~Drawing() { if( !mxCtrlForm.get() ) mxCtrlForm.reset( new ::oox::ole::EmbeddedForm( - mrFilter.getModelFactory(), mxDrawPage, mrFilter.getGraphicHelper() ) ); + mrFilter.getModel(), mxDrawPage, mrFilter.getGraphicHelper() ) ); return *mxCtrlForm; } diff --git a/oox/source/xls/drawingfragment.cxx b/oox/source/xls/drawingfragment.cxx index ad6bb97cdea9..4a32fe5d42e1 100644 --- a/oox/source/xls/drawingfragment.cxx +++ b/oox/source/xls/drawingfragment.cxx @@ -28,44 +28,30 @@ #include "oox/xls/drawingfragment.hxx" #include <com/sun/star/awt/Point.hpp> -#include <com/sun/star/beans/NamedValue.hpp> -#include <com/sun/star/form/binding/XBindableValue.hpp> -#include <com/sun/star/form/binding/XListEntrySink.hpp> -#include <com/sun/star/form/binding/XListEntrySource.hpp> -#include <com/sun/star/form/binding/XValueBinding.hpp> -#include "properties.hxx" -#include "oox/helper/attributelist.hxx" -#include "oox/helper/propertyset.hxx" #include "oox/drawingml/connectorshapecontext.hxx" #include "oox/drawingml/graphicshapecontext.hxx" #include "oox/drawingml/shapecontext.hxx" #include "oox/drawingml/shapegroupcontext.hxx" +#include "oox/helper/attributelist.hxx" +#include "oox/helper/propertyset.hxx" #include "oox/vml/vmlshape.hxx" #include "oox/vml/vmlshapecontainer.hxx" #include "oox/xls/formulaparser.hxx" #include "oox/xls/stylesbuffer.hxx" #include "oox/xls/themebuffer.hxx" #include "oox/xls/unitconverter.hxx" +#include "properties.hxx" + +namespace oox { +namespace xls { + +// ============================================================================ + +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::table; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing; -using ::rtl::OUString; -using ::com::sun::star::uno::Any; -using ::com::sun::star::uno::Exception; -using ::com::sun::star::uno::Reference; -using ::com::sun::star::uno::Sequence; -using ::com::sun::star::uno::UNO_QUERY; -using ::com::sun::star::uno::UNO_QUERY_THROW; -using ::com::sun::star::beans::NamedValue; -using ::com::sun::star::awt::Point; -using ::com::sun::star::awt::Rectangle; -using ::com::sun::star::awt::Size; -using ::com::sun::star::awt::XControlModel; -using ::com::sun::star::form::binding::XBindableValue; -using ::com::sun::star::form::binding::XListEntrySink; -using ::com::sun::star::form::binding::XListEntrySource; -using ::com::sun::star::form::binding::XValueBinding; -using ::com::sun::star::drawing::XShape; -using ::com::sun::star::table::CellAddress; -using ::com::sun::star::table::CellRangeAddress; using ::oox::core::ContextHandlerRef; using ::oox::drawingml::ConnectorShapeContext; using ::oox::drawingml::GraphicalObjectFrameContext; @@ -74,10 +60,10 @@ using ::oox::drawingml::Shape; using ::oox::drawingml::ShapePtr; using ::oox::drawingml::ShapeContext; using ::oox::drawingml::ShapeGroupContext; -// no using's for ::oox::vml, that may clash with ::oox::drawingml types +using ::rtl::OUString; -namespace oox { -namespace xls { + +// no using's for ::oox::vml, that may clash with ::oox::drawingml types // ============================================================================ @@ -557,7 +543,8 @@ bool VmlFindNoteFunc::operator()( const ::oox::vml::ShapeBase& rShape ) const VmlDrawing::VmlDrawing( const WorksheetHelper& rHelper ) : ::oox::vml::Drawing( rHelper.getOoxFilter(), rHelper.getDrawPage(), ::oox::vml::VMLDRAWING_EXCEL ), - WorksheetHelper( rHelper ) + WorksheetHelper( rHelper ), + maControlConv( rHelper.getBaseFilter().getModel(), rHelper.getBaseFilter().getGraphicHelper() ) { } @@ -592,65 +579,9 @@ void VmlDrawing::convertControlClientData( const Reference< XControlModel >& rxC // printable aPropSet.setProperty( PROP_Printable, rClientData.mbPrintObject ); - // linked cell - if( rClientData.maLinkedCell.getLength() > 0 ) try - { - Reference< XBindableValue > xBindable( rxCtrlModel, UNO_QUERY_THROW ); - - // convert formula string to cell address - FormulaParser& rParser = getFormulaParser(); - TokensFormulaContext aContext( true, false ); - aContext.setBaseAddress( CellAddress( getSheetIndex(), 0, 0 ) ); - rParser.importFormula( aContext, rClientData.maLinkedCell ); - CellAddress aAddress; - if( rParser.extractCellAddress( aAddress, aContext.getTokens(), true ) ) - { - // create argument sequence for createInstanceWithArguments() - NamedValue aValue; - aValue.Name = CREATE_OUSTRING( "BoundCell" ); - aValue.Value <<= aAddress; - Sequence< Any > aArgs( 1 ); - aArgs[ 0 ] <<= aValue; - - // create the CellValueBinding instance and set at the control model - Reference< XValueBinding > xBinding( getDocumentFactory()->createInstanceWithArguments( - CREATE_OUSTRING( "com.sun.star.table.CellValueBinding" ), aArgs ), UNO_QUERY_THROW ); - xBindable->setValueBinding( xBinding ); - } - } - catch( Exception& ) - { - } - - // source range - if( rClientData.maSourceRange.getLength() > 0 ) try - { - Reference< XListEntrySink > xEntrySink( rxCtrlModel, UNO_QUERY_THROW ); - - // convert formula string to cell range - FormulaParser& rParser = getFormulaParser(); - TokensFormulaContext aContext( true, false ); - aContext.setBaseAddress( CellAddress( getSheetIndex(), 0, 0 ) ); - rParser.importFormula( aContext, rClientData.maSourceRange ); - CellRangeAddress aRange; - if( rParser.extractCellRange( aRange, aContext.getTokens(), true ) ) - { - // create argument sequence for createInstanceWithArguments() - NamedValue aValue; - aValue.Name = CREATE_OUSTRING( "CellRange" ); - aValue.Value <<= aRange; - Sequence< Any > aArgs( 1 ); - aArgs[ 0 ] <<= aValue; - - // create the EntrySource instance and set at the control model - Reference< XListEntrySource > xEntrySource( getDocumentFactory()->createInstanceWithArguments( - CREATE_OUSTRING( "com.sun.star.table.CellRangeListSource" ), aArgs ), UNO_QUERY_THROW ); - xEntrySink->setListEntrySource( xEntrySource ); - } - } - catch( Exception& ) - { - } + // control sources + if( (rClientData.maLinkedCell.getLength() > 0) || (rClientData.maSourceRange.getLength() > 0) ) + maControlConv.bindToSources( rxCtrlModel, rClientData.maLinkedCell, rClientData.maSourceRange, getSheetIndex() ); } } diff --git a/oox/source/xls/excelfilter.cxx b/oox/source/xls/excelfilter.cxx index 1093b5cc7bfe..81cf12298784 100644 --- a/oox/source/xls/excelfilter.cxx +++ b/oox/source/xls/excelfilter.cxx @@ -27,35 +27,37 @@ ************************************************************************/ #include "oox/xls/excelfilter.hxx" +#include <com/sun/star/container/XNameContainer.hpp> +#include "oox/dump/biffdumper.hxx" +#include "oox/dump/xlsbdumper.hxx" #include "oox/helper/binaryinputstream.hxx" #include "oox/xls/biffdetector.hxx" #include "oox/xls/biffinputstream.hxx" #include "oox/xls/excelchartconverter.hxx" +#include "oox/ole/vbaproject.hxx" #include "oox/xls/stylesbuffer.hxx" #include "oox/xls/themebuffer.hxx" #include "oox/xls/workbookfragment.hxx" #include "oox/dump/biffdumper.hxx" #include "oox/dump/xlsbdumper.hxx" -using ::rtl::OUString; -using ::com::sun::star::uno::Any; -using ::com::sun::star::uno::Reference; -using ::com::sun::star::uno::Sequence; -using ::com::sun::star::uno::Exception; -using ::com::sun::star::uno::UNO_QUERY; -using ::com::sun::star::uno::XInterface; -using ::com::sun::star::lang::XComponent; -using ::com::sun::star::lang::XMultiServiceFactory; -using ::com::sun::star::xml::sax::XFastDocumentHandler; +namespace oox { +namespace xls { + +// ============================================================================ + +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::uno; + using ::oox::core::BinaryFilterBase; using ::oox::core::FragmentHandlerRef; using ::oox::core::Relation; using ::oox::core::Relations; using ::oox::core::XmlFilterBase; using ::oox::drawingml::table::TableStyleListPtr; - -namespace oox { -namespace xls { +using ::rtl::OUString; // ============================================================================ @@ -94,8 +96,8 @@ OUString SAL_CALL ExcelFilter_getImplementationName() throw() Sequence< OUString > SAL_CALL ExcelFilter_getSupportedServiceNames() throw() { - OUString aServiceName = CREATE_OUSTRING( "com.sun.star.comp.oox.ExcelFilter" ); - Sequence< OUString > aSeq( &aServiceName, 1 ); + Sequence< OUString > aSeq( 1 ); + aSeq[ 0 ] = CREATE_OUSTRING( "com.sun.star.comp.oox.ExcelFilter" ); return aSeq; } @@ -202,8 +204,8 @@ OUString SAL_CALL ExcelBiffFilter_getImplementationName() throw() Sequence< OUString > SAL_CALL ExcelBiffFilter_getSupportedServiceNames() throw() { - OUString aServiceName = CREATE_OUSTRING( "com.sun.star.comp.oox.ExcelBiffFilter" ); - Sequence< OUString > aSeq( &aServiceName, 1 ); + Sequence< OUString > aSeq( 1 ); + aSeq[ 0 ] = CREATE_OUSTRING( "com.sun.star.comp.oox.ExcelBiffFilter" ); return aSeq; } @@ -269,6 +271,62 @@ OUString ExcelBiffFilter::implGetImplementationName() const // ============================================================================ +OUString SAL_CALL ExcelVbaProjectFilter_getImplementationName() throw() +{ + return CREATE_OUSTRING( "com.sun.star.comp.oox.ExcelVbaProjectFilter" ); +} + +Sequence< OUString > SAL_CALL ExcelVbaProjectFilter_getSupportedServiceNames() throw() +{ + Sequence< OUString > aSeq( 1 ); + aSeq[ 0 ] = CREATE_OUSTRING( "com.sun.star.comp.oox.ExcelVBAProjectFilter" ); + return aSeq; +} + +Reference< XInterface > SAL_CALL ExcelVbaProjectFilter_createInstance( + const Reference< XMultiServiceFactory >& rxGlobalFactory ) throw( Exception ) +{ + return static_cast< ::cppu::OWeakObject* >( new ExcelVbaProjectFilter( rxGlobalFactory ) ); +} + +// ---------------------------------------------------------------------------- + +ExcelVbaProjectFilter::ExcelVbaProjectFilter( const Reference< XMultiServiceFactory >& rxGlobalFactory ) : + ExcelBiffFilter( rxGlobalFactory ) +{ +} + +bool ExcelVbaProjectFilter::importDocument() throw() +{ + bool bRet = false; + + // detect BIFF version and workbook stream name + OUString aWorkbookName; + BiffType eBiff = BiffDetector::detectStorageBiffVersion( aWorkbookName, getStorage() ); + OSL_ENSURE( eBiff == BIFF8, "ExcelVbaProjectFilter::ExcelVbaProjectFilter - invalid file format" ); + if( eBiff == BIFF8 ) + { + Reference< XNameContainer > xOleNameOverrideSink; + getArgument( CREATE_OUSTRING( "OleNameOverrideInfo" ) ) >>= xOleNameOverrideSink; + WorkbookHelperRoot aHelper( *this, eBiff ); + StorageRef xVbaPrjStrg = openSubStorage( CREATE_OUSTRING( "_VBA_PROJECT_CUR" ), false ); + if( xVbaPrjStrg.get() && xVbaPrjStrg->isStorage() ) + { + ole::VbaProject aVbaProject( getGlobalFactory(), Reference< com::sun::star::frame::XModel >( aHelper.getDocument(), UNO_QUERY ), CREATE_OUSTRING( "Calc" ) ); + aVbaProject.setOleOverridesSink( xOleNameOverrideSink ); + aVbaProject.importVbaProject( *xVbaPrjStrg, getGraphicHelper() ); + bRet = true; + } + } + return bRet; +} + +OUString ExcelVbaProjectFilter::implGetImplementationName() const +{ + return ExcelVbaProjectFilter_getImplementationName(); +} +// ============================================================================ + } // namespace xls } // namespace oox diff --git a/oox/source/xls/workbookhelper.cxx b/oox/source/xls/workbookhelper.cxx index f8a49c435244..6033601fb2d2 100644 --- a/oox/source/xls/workbookhelper.cxx +++ b/oox/source/xls/workbookhelper.cxx @@ -72,6 +72,7 @@ using ::rtl::OUString; using ::com::sun::star::uno::Any; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::uno::UNO_QUERY_THROW; using ::com::sun::star::uno::UNO_SET_THROW; |