/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ #include "xiescher.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "scitems.hxx" #include #include #include #include #include #include #include #include #include #include "document.hxx" #include "drwlayer.hxx" #include "userdat.hxx" #include "chartarr.hxx" #include "detfunc.hxx" #include "unonames.hxx" #include "convuno.hxx" #include "postit.hxx" #include "globstr.hrc" #include "fprogressbar.hxx" #include "xltracer.hxx" #include "xistream.hxx" #include "xihelper.hxx" #include "xiformula.hxx" #include "xilink.hxx" #include "xistyle.hxx" #include "xipage.hxx" #include "xichart.hxx" #include "xicontent.hxx" #include "scextopt.hxx" #include "namebuff.hxx" #include #include #include #include #include using ::rtl::OUString; using ::rtl::OUStringBuffer; 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::uno::UNO_SET_THROW; using ::com::sun::star::uno::XComponentContext; using ::com::sun::star::beans::NamedValue; using ::com::sun::star::lang::XMultiServiceFactory; using ::com::sun::star::container::XIndexContainer; using ::com::sun::star::container::XNameContainer; using ::com::sun::star::frame::XModel; using ::com::sun::star::awt::XControlModel; using ::com::sun::star::embed::XEmbeddedObject; using ::com::sun::star::embed::XEmbedPersist; using ::com::sun::star::drawing::XControlShape; using ::com::sun::star::drawing::XShape; using ::com::sun::star::form::XForm; using ::com::sun::star::form::XFormComponent; using ::com::sun::star::form::XFormsSupplier; using ::com::sun::star::form::binding::XBindableValue; using ::com::sun::star::form::binding::XValueBinding; using ::com::sun::star::form::binding::XListEntrySink; using ::com::sun::star::form::binding::XListEntrySource; using ::com::sun::star::script::ScriptEventDescriptor; using ::com::sun::star::script::XEventAttacherManager; using ::com::sun::star::table::CellAddress; using ::com::sun::star::table::CellRangeAddress; // ============================================================================ namespace { /** Helper class which mimics the auto_ptr< SdrObject > semantics, but calls SdrObject::Free instead of deleting the SdrObject directly. */ template< typename SdrObjType > class TSdrObjectPtr { public: inline explicit TSdrObjectPtr( SdrObjType* pObj = 0 ) : mpObj( pObj ) {} inline ~TSdrObjectPtr() { free(); } inline const SdrObjType* operator->() const { return mpObj; } inline SdrObjType* operator->() { return mpObj; } inline const SdrObjType* get() const { return mpObj; } inline SdrObjType* get() { return mpObj; } inline const SdrObjType& operator*() const { return *mpObj; } inline SdrObjType& operator*() { return *mpObj; } inline bool is() const { return mpObj != 0; } inline bool operator!() const { return mpObj == 0; } inline void reset( SdrObjType* pObj = 0 ) { free(); mpObj = pObj; } inline SdrObjType* release() { SdrObjType* pObj = mpObj; mpObj = 0; return pObj; } private: TSdrObjectPtr( const TSdrObjectPtr& ); // not implemented TSdrObjectPtr& operator=( TSdrObjectPtr& rxObj ); // not implemented inline void free() { SdrObject* pObj = mpObj; mpObj = 0; SdrObject::Free( pObj ); } private: SdrObjType* mpObj; }; typedef TSdrObjectPtr< SdrObject > SdrObjectPtr; } // namespace // Drawing objects ============================================================ XclImpDrawObjBase::XclImpDrawObjBase( const XclImpRoot& rRoot ) : XclImpRoot( rRoot ), mnObjId( EXC_OBJ_INVALID_ID ), mnObjType( EXC_OBJTYPE_UNKNOWN ), mnDffShapeId( 0 ), mnDffFlags( 0 ), mbHasAnchor( false ), mbHidden( false ), mbVisible( true ), mbPrintable( true ), mbAreaObj( false ), mbAutoMargin( true ), mbSimpleMacro( true ), mbProcessSdr( true ), mbInsertSdr( true ), mbCustomDff( false ) { } XclImpDrawObjBase::~XclImpDrawObjBase() { } XclImpDrawObjRef XclImpDrawObjBase::ReadObj3( const XclImpRoot& rRoot, XclImpStream& rStrm ) { XclImpDrawObjRef xDrawObj; if( rStrm.GetRecLeft() >= 30 ) { sal_uInt16 nObjType; rStrm.Ignore( 4 ); rStrm >> nObjType; switch( nObjType ) { case EXC_OBJTYPE_GROUP: xDrawObj.reset( new XclImpGroupObj( rRoot ) ); break; case EXC_OBJTYPE_LINE: xDrawObj.reset( new XclImpLineObj( rRoot ) ); break; case EXC_OBJTYPE_RECTANGLE: xDrawObj.reset( new XclImpRectObj( rRoot ) ); break; case EXC_OBJTYPE_OVAL: xDrawObj.reset( new XclImpOvalObj( rRoot ) ); break; case EXC_OBJTYPE_ARC: xDrawObj.reset( new XclImpArcObj( rRoot ) ); break; case EXC_OBJTYPE_CHART: xDrawObj.reset( new XclImpChartObj( rRoot ) ); break; case EXC_OBJTYPE_TEXT: xDrawObj.reset( new XclImpTextObj( rRoot ) ); break; case EXC_OBJTYPE_BUTTON: xDrawObj.reset( new XclImpButtonObj( rRoot ) ); break; case EXC_OBJTYPE_PICTURE: xDrawObj.reset( new XclImpPictureObj( rRoot ) ); break; default: OSL_TRACE( "XclImpDrawObjBase::ReadObj3 - unknown object type 0x%04hX", nObjType ); rRoot.GetTracer().TraceUnsupportedObjects(); xDrawObj.reset( new XclImpPhObj( rRoot ) ); } } xDrawObj->mnTab = rRoot.GetCurrScTab(); xDrawObj->ImplReadObj3( rStrm ); return xDrawObj; } XclImpDrawObjRef XclImpDrawObjBase::ReadObj4( const XclImpRoot& rRoot, XclImpStream& rStrm ) { XclImpDrawObjRef xDrawObj; if( rStrm.GetRecLeft() >= 30 ) { sal_uInt16 nObjType; rStrm.Ignore( 4 ); rStrm >> nObjType; switch( nObjType ) { case EXC_OBJTYPE_GROUP: xDrawObj.reset( new XclImpGroupObj( rRoot ) ); break; case EXC_OBJTYPE_LINE: xDrawObj.reset( new XclImpLineObj( rRoot ) ); break; case EXC_OBJTYPE_RECTANGLE: xDrawObj.reset( new XclImpRectObj( rRoot ) ); break; case EXC_OBJTYPE_OVAL: xDrawObj.reset( new XclImpOvalObj( rRoot ) ); break; case EXC_OBJTYPE_ARC: xDrawObj.reset( new XclImpArcObj( rRoot ) ); break; case EXC_OBJTYPE_CHART: xDrawObj.reset( new XclImpChartObj( rRoot ) ); break; case EXC_OBJTYPE_TEXT: xDrawObj.reset( new XclImpTextObj( rRoot ) ); break; case EXC_OBJTYPE_BUTTON: xDrawObj.reset( new XclImpButtonObj( rRoot ) ); break; case EXC_OBJTYPE_PICTURE: xDrawObj.reset( new XclImpPictureObj( rRoot ) ); break; case EXC_OBJTYPE_POLYGON: xDrawObj.reset( new XclImpPolygonObj( rRoot ) ); break; default: OSL_TRACE( "XclImpDrawObjBase::ReadObj4 - unknown object type 0x%04hX", nObjType ); rRoot.GetTracer().TraceUnsupportedObjects(); xDrawObj.reset( new XclImpPhObj( rRoot ) ); } } xDrawObj->mnTab = rRoot.GetCurrScTab(); xDrawObj->ImplReadObj4( rStrm ); return xDrawObj; } XclImpDrawObjRef XclImpDrawObjBase::ReadObj5( const XclImpRoot& rRoot, XclImpStream& rStrm ) { XclImpDrawObjRef xDrawObj; if( rStrm.GetRecLeft() >= 34 ) { sal_uInt16 nObjType(EXC_OBJTYPE_UNKNOWN); rStrm.Ignore( 4 ); rStrm >> nObjType; switch( nObjType ) { case EXC_OBJTYPE_GROUP: xDrawObj.reset( new XclImpGroupObj( rRoot ) ); break; case EXC_OBJTYPE_LINE: xDrawObj.reset( new XclImpLineObj( rRoot ) ); break; case EXC_OBJTYPE_RECTANGLE: xDrawObj.reset( new XclImpRectObj( rRoot ) ); break; case EXC_OBJTYPE_OVAL: xDrawObj.reset( new XclImpOvalObj( rRoot ) ); break; case EXC_OBJTYPE_ARC: xDrawObj.reset( new XclImpArcObj( rRoot ) ); break; case EXC_OBJTYPE_CHART: xDrawObj.reset( new XclImpChartObj( rRoot ) ); break; case EXC_OBJTYPE_TEXT: xDrawObj.reset( new XclImpTextObj( rRoot ) ); break; case EXC_OBJTYPE_BUTTON: xDrawObj.reset( new XclImpButtonObj( rRoot ) ); break; case EXC_OBJTYPE_PICTURE: xDrawObj.reset( new XclImpPictureObj( rRoot ) ); break; case EXC_OBJTYPE_POLYGON: xDrawObj.reset( new XclImpPolygonObj( rRoot ) ); break; case EXC_OBJTYPE_CHECKBOX: xDrawObj.reset( new XclImpCheckBoxObj( rRoot ) ); break; case EXC_OBJTYPE_OPTIONBUTTON: xDrawObj.reset( new XclImpOptionButtonObj( rRoot ) ); break; case EXC_OBJTYPE_EDIT: xDrawObj.reset( new XclImpEditObj( rRoot ) ); break; case EXC_OBJTYPE_LABEL: xDrawObj.reset( new XclImpLabelObj( rRoot ) ); break; case EXC_OBJTYPE_DIALOG: xDrawObj.reset( new XclImpDialogObj( rRoot ) ); break; case EXC_OBJTYPE_SPIN: xDrawObj.reset( new XclImpSpinButtonObj( rRoot ) ); break; case EXC_OBJTYPE_SCROLLBAR: xDrawObj.reset( new XclImpScrollBarObj( rRoot ) ); break; case EXC_OBJTYPE_LISTBOX: xDrawObj.reset( new XclImpListBoxObj( rRoot ) ); break; case EXC_OBJTYPE_GROUPBOX: xDrawObj.reset( new XclImpGroupBoxObj( rRoot ) ); break; case EXC_OBJTYPE_DROPDOWN: xDrawObj.reset( new XclImpDropDownObj( rRoot ) ); break; default: OSL_TRACE( "XclImpDrawObjBase::ReadObj5 - unknown object type 0x%04hX", nObjType ); rRoot.GetTracer().TraceUnsupportedObjects(); xDrawObj.reset( new XclImpPhObj( rRoot ) ); } } OSL_ENSURE(xDrawObj, "object import failed"); if (xDrawObj) { xDrawObj->mnTab = rRoot.GetCurrScTab(); xDrawObj->ImplReadObj5( rStrm ); } return xDrawObj; } XclImpDrawObjRef XclImpDrawObjBase::ReadObj8( const XclImpRoot& rRoot, XclImpStream& rStrm ) { XclImpDrawObjRef xDrawObj; if( rStrm.GetRecLeft() >= 10 ) { sal_uInt16 nSubRecId, nSubRecSize, nObjType; rStrm >> nSubRecId >> nSubRecSize >> nObjType; OSL_ENSURE( nSubRecId == EXC_ID_OBJCMO, "XclImpDrawObjBase::ReadObj8 - OBJCMO subrecord expected" ); if( (nSubRecId == EXC_ID_OBJCMO) && (nSubRecSize >= 6) ) { switch( nObjType ) { // in BIFF8, all simple objects support text case EXC_OBJTYPE_LINE: case EXC_OBJTYPE_ARC: xDrawObj.reset( new XclImpTextObj( rRoot ) ); // lines and arcs may be 2-dimensional xDrawObj->SetAreaObj( false ); break; // in BIFF8, all simple objects support text case EXC_OBJTYPE_RECTANGLE: case EXC_OBJTYPE_OVAL: case EXC_OBJTYPE_POLYGON: case EXC_OBJTYPE_DRAWING: case EXC_OBJTYPE_TEXT: xDrawObj.reset( new XclImpTextObj( rRoot ) ); break; case EXC_OBJTYPE_GROUP: xDrawObj.reset( new XclImpGroupObj( rRoot ) ); break; case EXC_OBJTYPE_CHART: xDrawObj.reset( new XclImpChartObj( rRoot ) ); break; case EXC_OBJTYPE_BUTTON: xDrawObj.reset( new XclImpButtonObj( rRoot ) ); break; case EXC_OBJTYPE_PICTURE: xDrawObj.reset( new XclImpPictureObj( rRoot ) ); break; case EXC_OBJTYPE_CHECKBOX: xDrawObj.reset( new XclImpCheckBoxObj( rRoot ) ); break; case EXC_OBJTYPE_OPTIONBUTTON: xDrawObj.reset( new XclImpOptionButtonObj( rRoot ) ); break; case EXC_OBJTYPE_EDIT: xDrawObj.reset( new XclImpEditObj( rRoot ) ); break; case EXC_OBJTYPE_LABEL: xDrawObj.reset( new XclImpLabelObj( rRoot ) ); break; case EXC_OBJTYPE_DIALOG: xDrawObj.reset( new XclImpDialogObj( rRoot ) ); break; case EXC_OBJTYPE_SPIN: xDrawObj.reset( new XclImpSpinButtonObj( rRoot ) ); break; case EXC_OBJTYPE_SCROLLBAR: xDrawObj.reset( new XclImpScrollBarObj( rRoot ) ); break; case EXC_OBJTYPE_LISTBOX: xDrawObj.reset( new XclImpListBoxObj( rRoot ) ); break; case EXC_OBJTYPE_GROUPBOX: xDrawObj.reset( new XclImpGroupBoxObj( rRoot ) ); break; case EXC_OBJTYPE_DROPDOWN: xDrawObj.reset( new XclImpDropDownObj( rRoot ) ); break; case EXC_OBJTYPE_NOTE: xDrawObj.reset( new XclImpNoteObj( rRoot ) ); break; default: OSL_TRACE( "XclImpDrawObjBase::ReadObj8 - unknown object type 0x%04hX", nObjType ); rRoot.GetTracer().TraceUnsupportedObjects(); xDrawObj.reset( new XclImpPhObj( rRoot ) ); } } } xDrawObj->mnTab = rRoot.GetCurrScTab(); xDrawObj->ImplReadObj8( rStrm ); return xDrawObj; } void XclImpDrawObjBase::SetAnchor( const XclObjAnchor& rAnchor ) { maAnchor = rAnchor; mbHasAnchor = true; } void XclImpDrawObjBase::SetDffData( const DffObjData& rDffObjData, const rtl::OUString& rObjName, const rtl::OUString& rHyperlink, bool bVisible, bool bAutoMargin ) { mnDffShapeId = rDffObjData.nShapeId; mnDffFlags = rDffObjData.nSpFlags; maObjName = rObjName; maHyperlink = rHyperlink; mbVisible = bVisible; mbAutoMargin = bAutoMargin; } OUString XclImpDrawObjBase::GetObjName() const { /* #i51348# Always return a non-empty name. Create English default names depending on the object type. This is not implemented as virtual functions in derived classes, as class type and object type may not match. */ return maObjName.isEmpty() ? GetObjectManager().GetDefaultObjName(*this) : maObjName; } const XclObjAnchor* XclImpDrawObjBase::GetAnchor() const { return mbHasAnchor ? &maAnchor : 0; } bool XclImpDrawObjBase::IsValidSize( const Rectangle& rAnchorRect ) const { // XclObjAnchor rounds up the width, width of 3 is the result of an Excel width of 0 return mbAreaObj ? ((rAnchorRect.GetWidth() > 3) && (rAnchorRect.GetHeight() > 1)) : ((rAnchorRect.GetWidth() > 3) || (rAnchorRect.GetHeight() > 1)); } ScRange XclImpDrawObjBase::GetUsedArea( SCTAB nScTab ) const { ScRange aScUsedArea( ScAddress::INITIALIZE_INVALID ); // #i44077# object inserted -> update used area for OLE object import if( mbHasAnchor && GetAddressConverter().ConvertRange( aScUsedArea, maAnchor, nScTab, nScTab, false ) ) { // reduce range, if object ends directly on borders between two columns or rows if( (maAnchor.mnRX == 0) && (aScUsedArea.aStart.Col() < aScUsedArea.aEnd.Col()) ) aScUsedArea.aEnd.IncCol( -1 ); if( (maAnchor.mnBY == 0) && (aScUsedArea.aStart.Row() < aScUsedArea.aEnd.Row()) ) aScUsedArea.aEnd.IncRow( -1 ); } return aScUsedArea; } sal_Size XclImpDrawObjBase::GetProgressSize() const { return DoGetProgressSize(); } SdrObject* XclImpDrawObjBase::CreateSdrObject( XclImpDffConverter& rDffConv, const Rectangle& rAnchorRect, bool bIsDff ) const { SdrObjectPtr xSdrObj; if( bIsDff && !mbCustomDff ) { rDffConv.Progress( GetProgressSize() ); } else { xSdrObj.reset( DoCreateSdrObj( rDffConv, rAnchorRect ) ); if( xSdrObj.is() ) xSdrObj->SetModel( rDffConv.GetModel() ); } return xSdrObj.release(); } void XclImpDrawObjBase::PreProcessSdrObject( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const { // default: front layer, derived classes may have to set other layer in DoPreProcessSdrObj() rSdrObj.NbcSetLayer( SC_LAYER_FRONT ); // set object name (GetObjName() will always return a non-empty name) rSdrObj.SetName( GetObjName() ); // #i39167# full width for all objects regardless of horizontal alignment rSdrObj.SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_BLOCK ) ); // automatic text margin if( mbAutoMargin ) { sal_Int32 nMargin = rDffConv.GetDefaultTextMargin(); rSdrObj.SetMergedItem( SdrTextLeftDistItem( nMargin ) ); rSdrObj.SetMergedItem( SdrTextRightDistItem( nMargin ) ); rSdrObj.SetMergedItem( SdrTextUpperDistItem( nMargin ) ); rSdrObj.SetMergedItem( SdrTextLowerDistItem( nMargin ) ); } // macro and hyperlink // removed oracle/sun check for mbSimpleMacro ( no idea what its for ) if (!maMacroName.isEmpty() || !maHyperlink.isEmpty()) { if( ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( &rSdrObj, sal_True ) ) { pInfo->SetMacro( XclTools::GetSbMacroUrl( maMacroName, GetDocShell() ) ); pInfo->SetHlink( maHyperlink ); } } // call virtual function for object type specific processing DoPreProcessSdrObj( rDffConv, rSdrObj ); } void XclImpDrawObjBase::PostProcessSdrObject( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const { // call virtual function for object type specific processing DoPostProcessSdrObj( rDffConv, rSdrObj ); } // protected ------------------------------------------------------------------ void XclImpDrawObjBase::ReadName5( XclImpStream& rStrm, sal_uInt16 nNameLen ) { maObjName = rtl::OUString(); if( nNameLen > 0 ) { // name length field is repeated before the name maObjName = rStrm.ReadByteString( false ); // skip padding byte for word boundaries if( rStrm.GetRecPos() & 1 ) rStrm.Ignore( 1 ); } } void XclImpDrawObjBase::ReadMacro3( XclImpStream& rStrm, sal_uInt16 nMacroSize ) { maMacroName = rtl::OUString(); rStrm.Ignore( nMacroSize ); // skip padding byte for word boundaries, not contained in nMacroSize if( rStrm.GetRecPos() & 1 ) rStrm.Ignore( 1 ); } void XclImpDrawObjBase::ReadMacro4( XclImpStream& rStrm, sal_uInt16 nMacroSize ) { maMacroName = rtl::OUString(); rStrm.Ignore( nMacroSize ); } void XclImpDrawObjBase::ReadMacro5( XclImpStream& rStrm, sal_uInt16 nMacroSize ) { maMacroName = rtl::OUString(); rStrm.Ignore( nMacroSize ); } void XclImpDrawObjBase::ReadMacro8( XclImpStream& rStrm ) { maMacroName = rtl::OUString(); if( rStrm.GetRecLeft() > 6 ) { // macro is stored in a tNameXR token containing a link to a defined name sal_uInt16 nFmlaSize; rStrm >> nFmlaSize; rStrm.Ignore( 4 ); OSL_ENSURE( nFmlaSize == 7, "XclImpDrawObjBase::ReadMacro - unexpected formula size" ); if( nFmlaSize == 7 ) { sal_uInt8 nTokenId; sal_uInt16 nExtSheet, nExtName; rStrm >> nTokenId >> nExtSheet >> nExtName; OSL_ENSURE( nTokenId == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ), "XclImpDrawObjBase::ReadMacro - tNameXR token expected" ); if( nTokenId == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ) ) maMacroName = GetLinkManager().GetMacroName( nExtSheet, nExtName ); } } } void XclImpDrawObjBase::ConvertLineStyle( SdrObject& rSdrObj, const XclObjLineData& rLineData ) const { if( rLineData.IsAuto() ) { XclObjLineData aAutoData; aAutoData.mnAuto = 0; ConvertLineStyle( rSdrObj, aAutoData ); } else { long nLineWidth = 35 * ::std::min( rLineData.mnWidth, EXC_OBJ_LINE_THICK ); rSdrObj.SetMergedItem( XLineWidthItem( nLineWidth ) ); rSdrObj.SetMergedItem( XLineColorItem( EMPTY_STRING, GetPalette().GetColor( rLineData.mnColorIdx ) ) ); rSdrObj.SetMergedItem( XLineJointItem( XLINEJOINT_MITER ) ); sal_uLong nDotLen = ::std::max< sal_uLong >( 70 * rLineData.mnWidth, 35 ); sal_uLong nDashLen = 3 * nDotLen; sal_uLong nDist = 2 * nDotLen; switch( rLineData.mnStyle ) { default: case EXC_OBJ_LINE_SOLID: rSdrObj.SetMergedItem( XLineStyleItem( XLINE_SOLID ) ); break; case EXC_OBJ_LINE_DASH: rSdrObj.SetMergedItem( XLineStyleItem( XLINE_DASH ) ); rSdrObj.SetMergedItem( XLineDashItem( EMPTY_STRING, XDash( XDASH_RECT, 0, nDotLen, 1, nDashLen, nDist ) ) ); break; case EXC_OBJ_LINE_DOT: rSdrObj.SetMergedItem( XLineStyleItem( XLINE_DASH ) ); rSdrObj.SetMergedItem( XLineDashItem( EMPTY_STRING, XDash( XDASH_RECT, 1, nDotLen, 0, nDashLen, nDist ) ) ); break; case EXC_OBJ_LINE_DASHDOT: rSdrObj.SetMergedItem( XLineStyleItem( XLINE_DASH ) ); rSdrObj.SetMergedItem( XLineDashItem( EMPTY_STRING, XDash( XDASH_RECT, 1, nDotLen, 1, nDashLen, nDist ) ) ); break; case EXC_OBJ_LINE_DASHDOTDOT: rSdrObj.SetMergedItem( XLineStyleItem( XLINE_DASH ) ); rSdrObj.SetMergedItem( XLineDashItem( EMPTY_STRING, XDash( XDASH_RECT, 2, nDotLen, 1, nDashLen, nDist ) ) ); break; case EXC_OBJ_LINE_MEDTRANS: rSdrObj.SetMergedItem( XLineStyleItem( XLINE_SOLID ) ); rSdrObj.SetMergedItem( XLineTransparenceItem( 50 ) ); break; case EXC_OBJ_LINE_DARKTRANS: rSdrObj.SetMergedItem( XLineStyleItem( XLINE_SOLID ) ); rSdrObj.SetMergedItem( XLineTransparenceItem( 25 ) ); break; case EXC_OBJ_LINE_LIGHTTRANS: rSdrObj.SetMergedItem( XLineStyleItem( XLINE_SOLID ) ); rSdrObj.SetMergedItem( XLineTransparenceItem( 75 ) ); break; case EXC_OBJ_LINE_NONE: rSdrObj.SetMergedItem( XLineStyleItem( XLINE_NONE ) ); break; } } } void XclImpDrawObjBase::ConvertFillStyle( SdrObject& rSdrObj, const XclObjFillData& rFillData ) const { if( rFillData.IsAuto() ) { XclObjFillData aAutoData; aAutoData.mnAuto = 0; ConvertFillStyle( rSdrObj, aAutoData ); } else if( rFillData.mnPattern == EXC_PATT_NONE ) { rSdrObj.SetMergedItem( XFillStyleItem( XFILL_NONE ) ); } else { Color aPattColor = GetPalette().GetColor( rFillData.mnPattColorIdx ); Color aBackColor = GetPalette().GetColor( rFillData.mnBackColorIdx ); if( (rFillData.mnPattern == EXC_PATT_SOLID) || (aPattColor == aBackColor) ) { rSdrObj.SetMergedItem( XFillStyleItem( XFILL_SOLID ) ); rSdrObj.SetMergedItem( XFillColorItem( EMPTY_STRING, aPattColor ) ); } else { static const sal_uInt8 sppnPatterns[][ 8 ] = { { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 }, { 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD }, { 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 }, { 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00 }, { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }, { 0x33, 0x66, 0xCC, 0x99, 0x33, 0x66, 0xCC, 0x99 }, { 0xCC, 0x66, 0x33, 0x99, 0xCC, 0x66, 0x33, 0x99 }, { 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33 }, { 0xCC, 0xFF, 0x33, 0xFF, 0xCC, 0xFF, 0x33, 0xFF }, { 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 }, { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }, { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 }, { 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 }, { 0xFF, 0x11, 0x11, 0x11, 0xFF, 0x11, 0x11, 0x11 }, { 0xAA, 0x44, 0xAA, 0x11, 0xAA, 0x44, 0xAA, 0x11 }, { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 }, { 0x80, 0x00, 0x08, 0x00, 0x80, 0x00, 0x08, 0x00 } }; const sal_uInt8* const pnPattern = sppnPatterns[ ::std::min< size_t >( rFillData.mnPattern - 2, SAL_N_ELEMENTS( sppnPatterns ) ) ]; // create 2-colored 8x8 DIB SvMemoryStream aMemStrm; aMemStrm << sal_uInt32( 12 ) << sal_Int16( 8 ) << sal_Int16( 8 ) << sal_uInt16( 1 ) << sal_uInt16( 1 ); aMemStrm << sal_uInt8( 0xFF ) << sal_uInt8( 0xFF ) << sal_uInt8( 0xFF ); aMemStrm << sal_uInt8( 0x00 ) << sal_uInt8( 0x00 ) << sal_uInt8( 0x00 ); for( size_t nIdx = 0; nIdx < 8; ++nIdx ) aMemStrm << sal_uInt32( pnPattern[ nIdx ] ); // 32-bit little-endian aMemStrm.Seek( STREAM_SEEK_TO_BEGIN ); Bitmap aBitmap; aBitmap.Read( aMemStrm, false ); XOBitmap aXOBitmap( aBitmap ); aXOBitmap.Bitmap2Array(); aXOBitmap.SetBitmapType( XBITMAP_8X8 ); if( aXOBitmap.GetBackgroundColor().GetColor() == COL_BLACK ) ::std::swap( aPattColor, aBackColor ); aXOBitmap.SetPixelColor( aPattColor ); aXOBitmap.SetBackgroundColor( aBackColor ); rSdrObj.SetMergedItem( XFillStyleItem( XFILL_BITMAP ) ); rSdrObj.SetMergedItem( XFillBitmapItem( EMPTY_STRING, aXOBitmap ) ); } } } void XclImpDrawObjBase::ConvertFrameStyle( SdrObject& rSdrObj, sal_uInt16 nFrameFlags ) const { if( ::get_flag( nFrameFlags, EXC_OBJ_FRAME_SHADOW ) ) { rSdrObj.SetMergedItem( SdrShadowItem( sal_True ) ); rSdrObj.SetMergedItem( SdrShadowXDistItem( 35 ) ); rSdrObj.SetMergedItem( SdrShadowYDistItem( 35 ) ); rSdrObj.SetMergedItem( SdrShadowColorItem( EMPTY_STRING, GetPalette().GetColor( EXC_COLOR_WINDOWTEXT ) ) ); } } Color XclImpDrawObjBase::GetSolidLineColor( const XclObjLineData& rLineData ) const { Color aColor( COL_TRANSPARENT ); if( rLineData.IsAuto() ) { XclObjLineData aAutoData; aAutoData.mnAuto = 0; aColor = GetSolidLineColor( aAutoData ); } else if( rLineData.mnStyle != EXC_OBJ_LINE_NONE ) { aColor = GetPalette().GetColor( rLineData.mnColorIdx ); } return aColor; } Color XclImpDrawObjBase::GetSolidFillColor( const XclObjFillData& rFillData ) const { Color aColor( COL_TRANSPARENT ); if( rFillData.IsAuto() ) { XclObjFillData aAutoData; aAutoData.mnAuto = 0; aColor = GetSolidFillColor( aAutoData ); } else if( rFillData.mnPattern != EXC_PATT_NONE ) { Color aPattColor = GetPalette().GetColor( rFillData.mnPattColorIdx ); Color aBackColor = GetPalette().GetColor( rFillData.mnBackColorIdx ); aColor = XclTools::GetPatternColor( aPattColor, aBackColor, rFillData.mnPattern ); } return aColor; } void XclImpDrawObjBase::DoReadObj3( XclImpStream&, sal_uInt16 ) { } void XclImpDrawObjBase::DoReadObj4( XclImpStream&, sal_uInt16 ) { } void XclImpDrawObjBase::DoReadObj5( XclImpStream&, sal_uInt16, sal_uInt16 ) { } void XclImpDrawObjBase::DoReadObj8SubRec( XclImpStream&, sal_uInt16, sal_uInt16 ) { } sal_Size XclImpDrawObjBase::DoGetProgressSize() const { return 1; } SdrObject* XclImpDrawObjBase::DoCreateSdrObj( XclImpDffConverter& rDffConv, const Rectangle& ) const { rDffConv.Progress( GetProgressSize() ); return 0; } void XclImpDrawObjBase::DoPreProcessSdrObj( XclImpDffConverter&, SdrObject& ) const { // trace if object is not printable if( !IsPrintable() ) GetTracer().TraceObjectNotPrintable(); } void XclImpDrawObjBase::DoPostProcessSdrObj( XclImpDffConverter&, SdrObject& ) const { } void XclImpDrawObjBase::ImplReadObj3( XclImpStream& rStrm ) { // back to offset 4 (ignore object count field) rStrm.Seek( 4 ); sal_uInt16 nObjFlags, nMacroSize; rStrm >> mnObjType >> mnObjId >> nObjFlags >> maAnchor >> nMacroSize; rStrm.Ignore( 2 ); mbHasAnchor = true; mbHidden = ::get_flag( nObjFlags, EXC_OBJ_HIDDEN ); mbVisible = ::get_flag( nObjFlags, EXC_OBJ_VISIBLE ); DoReadObj3( rStrm, nMacroSize ); } void XclImpDrawObjBase::ImplReadObj4( XclImpStream& rStrm ) { // back to offset 4 (ignore object count field) rStrm.Seek( 4 ); sal_uInt16 nObjFlags, nMacroSize; rStrm >> mnObjType >> mnObjId >> nObjFlags >> maAnchor >> nMacroSize; rStrm.Ignore( 2 ); mbHasAnchor = true; mbHidden = ::get_flag( nObjFlags, EXC_OBJ_HIDDEN ); mbVisible = ::get_flag( nObjFlags, EXC_OBJ_VISIBLE ); mbPrintable = ::get_flag( nObjFlags, EXC_OBJ_PRINTABLE ); DoReadObj4( rStrm, nMacroSize ); } void XclImpDrawObjBase::ImplReadObj5( XclImpStream& rStrm ) { // back to offset 4 (ignore object count field) rStrm.Seek( 4 ); sal_uInt16 nObjFlags, nMacroSize, nNameLen; rStrm >> mnObjType >> mnObjId >> nObjFlags >> maAnchor >> nMacroSize; rStrm.Ignore( 2 ); rStrm >> nNameLen; rStrm.Ignore( 2 ); mbHasAnchor = true; mbHidden = ::get_flag( nObjFlags, EXC_OBJ_HIDDEN ); mbVisible = ::get_flag( nObjFlags, EXC_OBJ_VISIBLE ); mbPrintable = ::get_flag( nObjFlags, EXC_OBJ_PRINTABLE ); DoReadObj5( rStrm, nNameLen, nMacroSize ); } void XclImpDrawObjBase::ImplReadObj8( XclImpStream& rStrm ) { // back to beginning rStrm.Seek( EXC_REC_SEEK_TO_BEGIN ); bool bLoop = true; while( bLoop && (rStrm.GetRecLeft() >= 4) ) { sal_uInt16 nSubRecId, nSubRecSize; rStrm >> nSubRecId >> nSubRecSize; rStrm.PushPosition(); // sometimes the last subrecord has an invalid length (OBJLBSDATA) -> min() nSubRecSize = static_cast< sal_uInt16 >( ::std::min< sal_Size >( nSubRecSize, rStrm.GetRecLeft() ) ); switch( nSubRecId ) { case EXC_ID_OBJCMO: OSL_ENSURE( rStrm.GetRecPos() == 4, "XclImpDrawObjBase::ImplReadObj8 - unexpected OBJCMO subrecord" ); if( (rStrm.GetRecPos() == 4) && (nSubRecSize >= 6) ) { sal_uInt16 nObjFlags; rStrm >> mnObjType >> mnObjId >> nObjFlags; mbPrintable = ::get_flag( nObjFlags, EXC_OBJCMO_PRINTABLE ); } break; case EXC_ID_OBJMACRO: ReadMacro8( rStrm ); break; case EXC_ID_OBJEND: bLoop = false; break; default: DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize ); } rStrm.PopPosition(); rStrm.Ignore( nSubRecSize ); } /* Call DoReadObj8SubRec() with EXC_ID_OBJEND for further stream processing (e.g. charts), even if the OBJEND subrecord is missing. */ DoReadObj8SubRec( rStrm, EXC_ID_OBJEND, 0 ); /* Pictures that Excel reads from BIFF5 and writes to BIFF8 still have the IMGDATA record following the OBJ record (but they use the image data stored in DFF). The IMGDATA record may be continued by several CONTINUE records. But the last CONTINUE record may be in fact an MSODRAWING record that contains the DFF data of the next drawing object! So we have to skip just enough CONTINUE records to look at the next MSODRAWING/CONTINUE record. */ if( (rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord() ) { sal_uInt32 nDataSize; rStrm.Ignore( 4 ); rStrm >> nDataSize; nDataSize -= rStrm.GetRecLeft(); // skip following CONTINUE records until IMGDATA ends while( (nDataSize > 0) && (rStrm.GetNextRecId() == EXC_ID_CONT) && rStrm.StartNextRecord() ) { OSL_ENSURE( nDataSize >= rStrm.GetRecLeft(), "XclImpDrawObjBase::ImplReadObj8 - CONTINUE too long" ); nDataSize -= ::std::min< sal_uInt32 >( rStrm.GetRecLeft(), nDataSize ); } OSL_ENSURE( nDataSize == 0, "XclImpDrawObjBase::ImplReadObj8 - missing CONTINUE records" ); // next record may be MSODRAWING or CONTINUE or anything else } } // ---------------------------------------------------------------------------- void XclImpDrawObjVector::InsertGrouped( XclImpDrawObjRef xDrawObj ) { if( !empty() ) if( XclImpGroupObj* pGroupObj = dynamic_cast< XclImpGroupObj* >( back().get() ) ) if( pGroupObj->TryInsert( xDrawObj ) ) return; push_back( xDrawObj ); } sal_Size XclImpDrawObjVector::GetProgressSize() const { sal_Size nProgressSize = 0; for( const_iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt ) nProgressSize += (*aIt)->GetProgressSize(); return nProgressSize; } // ---------------------------------------------------------------------------- XclImpPhObj::XclImpPhObj( const XclImpRoot& rRoot ) : XclImpDrawObjBase( rRoot ) { SetProcessSdrObj( false ); } // ---------------------------------------------------------------------------- XclImpGroupObj::XclImpGroupObj( const XclImpRoot& rRoot ) : XclImpDrawObjBase( rRoot ), mnFirstUngrouped( 0 ) { } bool XclImpGroupObj::TryInsert( XclImpDrawObjRef xDrawObj ) { if( xDrawObj->GetObjId() == mnFirstUngrouped ) return false; // insert into own list or into nested group maChildren.InsertGrouped( xDrawObj ); return true; } void XclImpGroupObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize ) { rStrm.Ignore( 4 ); rStrm >> mnFirstUngrouped; rStrm.Ignore( 16 ); ReadMacro3( rStrm, nMacroSize ); } void XclImpGroupObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize ) { rStrm.Ignore( 4 ); rStrm >> mnFirstUngrouped; rStrm.Ignore( 16 ); ReadMacro4( rStrm, nMacroSize ); } void XclImpGroupObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ) { rStrm.Ignore( 4 ); rStrm >> mnFirstUngrouped; rStrm.Ignore( 16 ); ReadName5( rStrm, nNameLen ); ReadMacro5( rStrm, nMacroSize ); } sal_Size XclImpGroupObj::DoGetProgressSize() const { return XclImpDrawObjBase::DoGetProgressSize() + maChildren.GetProgressSize(); } SdrObject* XclImpGroupObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const Rectangle& /*rAnchorRect*/ ) const { TSdrObjectPtr< SdrObjGroup > xSdrObj( new SdrObjGroup ); // child objects in BIFF2-BIFF5 have absolute size, not needed to pass own anchor rectangle SdrObjList& rObjList = *xSdrObj->GetSubList(); // SdrObjGroup always returns existing sublist for( XclImpDrawObjVector::const_iterator aIt = maChildren.begin(), aEnd = maChildren.end(); aIt != aEnd; ++aIt ) rDffConv.ProcessObject( rObjList, **aIt ); rDffConv.Progress(); return xSdrObj.release(); } // ---------------------------------------------------------------------------- XclImpLineObj::XclImpLineObj( const XclImpRoot& rRoot ) : XclImpDrawObjBase( rRoot ), mnArrows( 0 ), mnStartPoint( EXC_OBJ_LINE_TL ) { SetAreaObj( false ); } void XclImpLineObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize ) { rStrm >> maLineData >> mnArrows >> mnStartPoint; rStrm.Ignore( 1 ); ReadMacro3( rStrm, nMacroSize ); } void XclImpLineObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize ) { rStrm >> maLineData >> mnArrows >> mnStartPoint; rStrm.Ignore( 1 ); ReadMacro4( rStrm, nMacroSize ); } void XclImpLineObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ) { rStrm >> maLineData >> mnArrows >> mnStartPoint; rStrm.Ignore( 1 ); ReadName5( rStrm, nNameLen ); ReadMacro5( rStrm, nMacroSize ); } SdrObject* XclImpLineObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const Rectangle& rAnchorRect ) const { ::basegfx::B2DPolygon aB2DPolygon; switch( mnStartPoint ) { default: case EXC_OBJ_LINE_TL: aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Top() ) ); aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Bottom() ) ); break; case EXC_OBJ_LINE_TR: aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Top() ) ); aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Bottom() ) ); break; case EXC_OBJ_LINE_BR: aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Bottom() ) ); aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Top() ) ); break; case EXC_OBJ_LINE_BL: aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Bottom() ) ); aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Top() ) ); break; } SdrObjectPtr xSdrObj( new SdrPathObj( OBJ_LINE, ::basegfx::B2DPolyPolygon( aB2DPolygon ) ) ); ConvertLineStyle( *xSdrObj, maLineData ); // line ends sal_uInt8 nArrowType = ::extract_value< sal_uInt8 >( mnArrows, 0, 4 ); bool bLineStart = false; bool bLineEnd = false; bool bFilled = false; switch( nArrowType ) { case EXC_OBJ_ARROW_OPEN: bLineStart = false; bLineEnd = true; bFilled = false; break; case EXC_OBJ_ARROW_OPENBOTH: bLineStart = true; bLineEnd = true; bFilled = false; break; case EXC_OBJ_ARROW_FILLED: bLineStart = false; bLineEnd = true; bFilled = true; break; case EXC_OBJ_ARROW_FILLEDBOTH: bLineStart = true; bLineEnd = true; bFilled = true; break; } if( bLineStart || bLineEnd ) { sal_uInt8 nArrowWidth = ::extract_value< sal_uInt8 >( mnArrows, 4, 4 ); double fArrowWidth = 3.0; switch( nArrowWidth ) { case EXC_OBJ_ARROW_NARROW: fArrowWidth = 2.0; break; case EXC_OBJ_ARROW_MEDIUM: fArrowWidth = 3.0; break; case EXC_OBJ_ARROW_WIDE: fArrowWidth = 5.0; break; } sal_uInt8 nArrowLength = ::extract_value< sal_uInt8 >( mnArrows, 8, 4 ); double fArrowLength = 3.0; switch( nArrowLength ) { case EXC_OBJ_ARROW_NARROW: fArrowLength = 2.5; break; case EXC_OBJ_ARROW_MEDIUM: fArrowLength = 3.5; break; case EXC_OBJ_ARROW_WIDE: fArrowLength = 6.0; break; } ::basegfx::B2DPolygon aArrowPoly; #define EXC_ARROW_POINT( x, y ) ::basegfx::B2DPoint( fArrowWidth * (x), fArrowLength * (y) ) if( bFilled ) { aArrowPoly.append( EXC_ARROW_POINT( 0, 100 ) ); aArrowPoly.append( EXC_ARROW_POINT( 50, 0 ) ); aArrowPoly.append( EXC_ARROW_POINT( 100, 100 ) ); } else { sal_uInt8 nLineWidth = ::limit_cast< sal_uInt8 >( maLineData.mnWidth, EXC_OBJ_LINE_THIN, EXC_OBJ_LINE_THICK ); aArrowPoly.append( EXC_ARROW_POINT( 50, 0 ) ); aArrowPoly.append( EXC_ARROW_POINT( 100, 100 - 3 * nLineWidth ) ); aArrowPoly.append( EXC_ARROW_POINT( 100 - 5 * nLineWidth, 100 ) ); aArrowPoly.append( EXC_ARROW_POINT( 50, 12 * nLineWidth ) ); aArrowPoly.append( EXC_ARROW_POINT( 5 * nLineWidth, 100 ) ); aArrowPoly.append( EXC_ARROW_POINT( 0, 100 - 3 * nLineWidth ) ); } #undef EXC_ARROW_POINT ::basegfx::B2DPolyPolygon aArrowPolyPoly( aArrowPoly ); long nWidth = static_cast< long >( 125 * fArrowWidth ); if( bLineStart ) { xSdrObj->SetMergedItem( XLineStartItem( EMPTY_STRING, aArrowPolyPoly ) ); xSdrObj->SetMergedItem( XLineStartWidthItem( nWidth ) ); xSdrObj->SetMergedItem( XLineStartCenterItem( false ) ); } if( bLineEnd ) { xSdrObj->SetMergedItem( XLineEndItem( EMPTY_STRING, aArrowPolyPoly ) ); xSdrObj->SetMergedItem( XLineEndWidthItem( nWidth ) ); xSdrObj->SetMergedItem( XLineEndCenterItem( false ) ); } } rDffConv.Progress(); return xSdrObj.release(); } // ---------------------------------------------------------------------------- XclImpRectObj::XclImpRectObj( const XclImpRoot& rRoot ) : XclImpDrawObjBase( rRoot ), mnFrameFlags( 0 ) { SetAreaObj( true ); } void XclImpRectObj::ReadFrameData( XclImpStream& rStrm ) { rStrm >> maFillData >> maLineData >> mnFrameFlags; } void XclImpRectObj::ConvertRectStyle( SdrObject& rSdrObj ) const { ConvertLineStyle( rSdrObj, maLineData ); ConvertFillStyle( rSdrObj, maFillData ); ConvertFrameStyle( rSdrObj, mnFrameFlags ); } void XclImpRectObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize ) { ReadFrameData( rStrm ); ReadMacro3( rStrm, nMacroSize ); } void XclImpRectObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize ) { ReadFrameData( rStrm ); ReadMacro4( rStrm, nMacroSize ); } void XclImpRectObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ) { ReadFrameData( rStrm ); ReadName5( rStrm, nNameLen ); ReadMacro5( rStrm, nMacroSize ); } SdrObject* XclImpRectObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const Rectangle& rAnchorRect ) const { SdrObjectPtr xSdrObj( new SdrRectObj( rAnchorRect ) ); ConvertRectStyle( *xSdrObj ); rDffConv.Progress(); return xSdrObj.release(); } // ---------------------------------------------------------------------------- XclImpOvalObj::XclImpOvalObj( const XclImpRoot& rRoot ) : XclImpRectObj( rRoot ) { } SdrObject* XclImpOvalObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const Rectangle& rAnchorRect ) const { SdrObjectPtr xSdrObj( new SdrCircObj( OBJ_CIRC, rAnchorRect ) ); ConvertRectStyle( *xSdrObj ); rDffConv.Progress(); return xSdrObj.release(); } // ---------------------------------------------------------------------------- XclImpArcObj::XclImpArcObj( const XclImpRoot& rRoot ) : XclImpDrawObjBase( rRoot ), mnQuadrant( EXC_OBJ_ARC_TR ) { SetAreaObj( false ); // arc may be 2-dimensional } void XclImpArcObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize ) { rStrm >> maFillData >> maLineData >> mnQuadrant; rStrm.Ignore( 1 ); ReadMacro3( rStrm, nMacroSize ); } void XclImpArcObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize ) { rStrm >> maFillData >> maLineData >> mnQuadrant; rStrm.Ignore( 1 ); ReadMacro4( rStrm, nMacroSize ); } void XclImpArcObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ) { rStrm >> maFillData >> maLineData >> mnQuadrant; rStrm.Ignore( 1 ); ReadName5( rStrm, nNameLen ); ReadMacro5( rStrm, nMacroSize ); } SdrObject* XclImpArcObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const Rectangle& rAnchorRect ) const { Rectangle aNewRect = rAnchorRect; long nStartAngle = 0; long nEndAngle = 0; switch( mnQuadrant ) { default: case EXC_OBJ_ARC_TR: nStartAngle = 0; nEndAngle = 9000; aNewRect.Left() -= rAnchorRect.GetWidth(); aNewRect.Bottom() += rAnchorRect.GetHeight(); break; case EXC_OBJ_ARC_TL: nStartAngle = 9000; nEndAngle = 18000; aNewRect.Right() += rAnchorRect.GetWidth(); aNewRect.Bottom() += rAnchorRect.GetHeight(); break; case EXC_OBJ_ARC_BL: nStartAngle = 18000; nEndAngle = 27000; aNewRect.Right() += rAnchorRect.GetWidth(); aNewRect.Top() -= rAnchorRect.GetHeight(); break; case EXC_OBJ_ARC_BR: nStartAngle = 27000; nEndAngle = 0; aNewRect.Left() -= rAnchorRect.GetWidth(); aNewRect.Top() -= rAnchorRect.GetHeight(); break; } SdrObjKind eObjKind = maFillData.IsFilled() ? OBJ_SECT : OBJ_CARC; SdrObjectPtr xSdrObj( new SdrCircObj( eObjKind, aNewRect, nStartAngle, nEndAngle ) ); ConvertFillStyle( *xSdrObj, maFillData ); ConvertLineStyle( *xSdrObj, maLineData ); rDffConv.Progress(); return xSdrObj.release(); } // ---------------------------------------------------------------------------- XclImpPolygonObj::XclImpPolygonObj( const XclImpRoot& rRoot ) : XclImpRectObj( rRoot ), mnPolyFlags( 0 ), mnPointCount( 0 ) { SetAreaObj( false ); // polygon may be 2-dimensional } void XclImpPolygonObj::ReadCoordList( XclImpStream& rStrm ) { if( (rStrm.GetNextRecId() == EXC_ID_COORDLIST) && rStrm.StartNextRecord() ) { OSL_ENSURE( rStrm.GetRecLeft() / 4 == mnPointCount, "XclImpPolygonObj::ReadCoordList - wrong polygon point count" ); while( rStrm.GetRecLeft() >= 4 ) { sal_uInt16 nX, nY; rStrm >> nX >> nY; maCoords.push_back( Point( nX, nY ) ); } } } void XclImpPolygonObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize ) { ReadFrameData( rStrm ); rStrm >> mnPolyFlags; rStrm.Ignore( 10 ); rStrm >> mnPointCount; rStrm.Ignore( 8 ); ReadMacro4( rStrm, nMacroSize ); ReadCoordList( rStrm ); } void XclImpPolygonObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ) { ReadFrameData( rStrm ); rStrm >> mnPolyFlags; rStrm.Ignore( 10 ); rStrm >> mnPointCount; rStrm.Ignore( 8 ); ReadName5( rStrm, nNameLen ); ReadMacro5( rStrm, nMacroSize ); ReadCoordList( rStrm ); } namespace { ::basegfx::B2DPoint lclGetPolyPoint( const Rectangle& rAnchorRect, const Point& rPoint ) { return ::basegfx::B2DPoint( rAnchorRect.Left() + static_cast< sal_Int32 >( ::std::min< double >( rPoint.X(), 16384.0 ) / 16384.0 * rAnchorRect.GetWidth() + 0.5 ), rAnchorRect.Top() + static_cast< sal_Int32 >( ::std::min< double >( rPoint.Y(), 16384.0 ) / 16384.0 * rAnchorRect.GetHeight() + 0.5 ) ); } } // namespace SdrObject* XclImpPolygonObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const Rectangle& rAnchorRect ) const { SdrObjectPtr xSdrObj; if( maCoords.size() >= 2 ) { // create the polygon ::basegfx::B2DPolygon aB2DPolygon; for( PointVector::const_iterator aIt = maCoords.begin(), aEnd = maCoords.end(); aIt != aEnd; ++aIt ) aB2DPolygon.append( lclGetPolyPoint( rAnchorRect, *aIt ) ); // close polygon if specified if( ::get_flag( mnPolyFlags, EXC_OBJ_POLY_CLOSED ) && (maCoords.front() != maCoords.back()) ) aB2DPolygon.append( lclGetPolyPoint( rAnchorRect, maCoords.front() ) ); // create the SdrObject SdrObjKind eObjKind = maFillData.IsFilled() ? OBJ_PATHPOLY : OBJ_PATHPLIN; xSdrObj.reset( new SdrPathObj( eObjKind, ::basegfx::B2DPolyPolygon( aB2DPolygon ) ) ); ConvertRectStyle( *xSdrObj ); } rDffConv.Progress(); return xSdrObj.release(); } // ---------------------------------------------------------------------------- void XclImpObjTextData::ReadByteString( XclImpStream& rStrm ) { mxString.reset(); if( maData.mnTextLen > 0 ) { mxString.reset( new XclImpString( rStrm.ReadRawByteString( maData.mnTextLen ) ) ); // skip padding byte for word boundaries if( rStrm.GetRecPos() & 1 ) rStrm.Ignore( 1 ); } } void XclImpObjTextData::ReadFormats( XclImpStream& rStrm ) { if( mxString ) mxString->ReadObjFormats( rStrm, maData.mnFormatSize ); else rStrm.Ignore( maData.mnFormatSize ); } // ---------------------------------------------------------------------------- XclImpTextObj::XclImpTextObj( const XclImpRoot& rRoot ) : XclImpRectObj( rRoot ) { } void XclImpTextObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize ) { ReadFrameData( rStrm ); maTextData.maData.ReadObj3( rStrm ); ReadMacro3( rStrm, nMacroSize ); maTextData.ReadByteString( rStrm ); maTextData.ReadFormats( rStrm ); } void XclImpTextObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize ) { ReadFrameData( rStrm ); maTextData.maData.ReadObj3( rStrm ); ReadMacro4( rStrm, nMacroSize ); maTextData.ReadByteString( rStrm ); maTextData.ReadFormats( rStrm ); } void XclImpTextObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ) { ReadFrameData( rStrm ); maTextData.maData.ReadObj5( rStrm ); ReadName5( rStrm, nNameLen ); ReadMacro5( rStrm, nMacroSize ); maTextData.ReadByteString( rStrm ); rStrm.Ignore( maTextData.maData.mnLinkSize ); // ignore text link formula maTextData.ReadFormats( rStrm ); } SdrObject* XclImpTextObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const Rectangle& rAnchorRect ) const { TSdrObjectPtr< SdrObjCustomShape > xSdrObj( new SdrObjCustomShape ); xSdrObj->NbcSetSnapRect( rAnchorRect ); OUString aRectType = CREATE_OUSTRING( "rectangle" ); xSdrObj->MergeDefaultAttributes( &aRectType ); ConvertRectStyle( *xSdrObj ); sal_Bool bAutoSize = ::get_flag( maTextData.maData.mnFlags, EXC_OBJ_TEXT_AUTOSIZE ); xSdrObj->SetMergedItem( SdrTextAutoGrowWidthItem( bAutoSize ) ); xSdrObj->SetMergedItem( SdrTextAutoGrowHeightItem( bAutoSize ) ); xSdrObj->SetMergedItem( SdrTextWordWrapItem( sal_True ) ); rDffConv.Progress(); return xSdrObj.release(); } void XclImpTextObj::DoPreProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const { // set text data if( SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( &rSdrObj ) ) { if( maTextData.mxString ) { if( maTextData.mxString->IsRich() ) { // rich text ::std::auto_ptr< EditTextObject > xEditObj( XclImpStringHelper::CreateTextObject( GetRoot(), *maTextData.mxString ) ); OutlinerParaObject* pOutlineObj = new OutlinerParaObject( *xEditObj ); pOutlineObj->SetOutlinerMode( OUTLINERMODE_TEXTOBJECT ); // text object takes ownership of the outliner object pTextObj->NbcSetOutlinerParaObject( pOutlineObj ); } else { // plain text pTextObj->NbcSetText( maTextData.mxString->GetText() ); } /* #i96858# Do not apply any formatting if there is no text. SdrObjCustomShape::SetVerticalWriting (initiated from SetMergedItem) calls SdrTextObj::ForceOutlinerParaObject which ensures that we can erroneously write a ClientTextbox record (with no content) while exporting to XLS, which can cause a corrupted exported document. */ SvxAdjust eHorAlign = SVX_ADJUST_LEFT; SdrTextVertAdjust eVerAlign = SDRTEXTVERTADJUST_TOP; // orientation (this is only a fake, drawing does not support real text orientation) namespace csst = ::com::sun::star::text; csst::WritingMode eWriteMode = csst::WritingMode_LR_TB; switch( maTextData.maData.mnOrient ) { default: case EXC_OBJ_ORIENT_NONE: { eWriteMode = csst::WritingMode_LR_TB; switch( maTextData.maData.GetHorAlign() ) { case EXC_OBJ_HOR_LEFT: eHorAlign = SVX_ADJUST_LEFT; break; case EXC_OBJ_HOR_CENTER: eHorAlign = SVX_ADJUST_CENTER; break; case EXC_OBJ_HOR_RIGHT: eHorAlign = SVX_ADJUST_RIGHT; break; case EXC_OBJ_HOR_JUSTIFY: eHorAlign = SVX_ADJUST_BLOCK; break; } switch( maTextData.maData.GetVerAlign() ) { case EXC_OBJ_VER_TOP: eVerAlign = SDRTEXTVERTADJUST_TOP; break; case EXC_OBJ_VER_CENTER: eVerAlign = SDRTEXTVERTADJUST_CENTER; break; case EXC_OBJ_VER_BOTTOM: eVerAlign = SDRTEXTVERTADJUST_BOTTOM; break; case EXC_OBJ_VER_JUSTIFY: eVerAlign = SDRTEXTVERTADJUST_BLOCK; break; } } break; case EXC_OBJ_ORIENT_90CCW: { if( SdrObjCustomShape* pObjCustomShape = dynamic_cast< SdrObjCustomShape* >( &rSdrObj ) ) { double fAngle = 180.0; com::sun::star::beans::PropertyValue aTextRotateAngle; aTextRotateAngle.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "TextRotateAngle" ) ); aTextRotateAngle.Value <<= fAngle; SdrCustomShapeGeometryItem aGeometryItem((SdrCustomShapeGeometryItem&)pObjCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY )); aGeometryItem.SetPropertyValue( aTextRotateAngle ); pObjCustomShape->SetMergedItem( aGeometryItem ); } eWriteMode = csst::WritingMode_TB_RL; switch( maTextData.maData.GetHorAlign() ) { case EXC_OBJ_HOR_LEFT: eVerAlign = SDRTEXTVERTADJUST_TOP; break; case EXC_OBJ_HOR_CENTER: eVerAlign = SDRTEXTVERTADJUST_CENTER; break; case EXC_OBJ_HOR_RIGHT: eVerAlign = SDRTEXTVERTADJUST_BOTTOM; break; case EXC_OBJ_HOR_JUSTIFY: eVerAlign = SDRTEXTVERTADJUST_BLOCK; break; } MSO_Anchor eTextAnchor = (MSO_Anchor)rDffConv.GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop ); switch( eTextAnchor ) { case mso_anchorTopCentered : case mso_anchorMiddleCentered : case mso_anchorBottomCentered : { eHorAlign = SVX_ADJUST_CENTER; } break; default: { switch( maTextData.maData.GetVerAlign() ) { case EXC_OBJ_VER_TOP: eHorAlign = SVX_ADJUST_RIGHT; break; case EXC_OBJ_VER_CENTER: eHorAlign = SVX_ADJUST_CENTER; break; case EXC_OBJ_VER_BOTTOM: eHorAlign = SVX_ADJUST_LEFT; break; case EXC_OBJ_VER_JUSTIFY: eHorAlign = SVX_ADJUST_BLOCK; break; } } } } break; case EXC_OBJ_ORIENT_STACKED: // PASSTHROUGH INTENDED { // sj: STACKED is not supported, maybe it can be optimized here a bit } case EXC_OBJ_ORIENT_90CW: { eWriteMode = csst::WritingMode_TB_RL; switch( maTextData.maData.GetHorAlign() ) { case EXC_OBJ_HOR_LEFT: eVerAlign = SDRTEXTVERTADJUST_BOTTOM; break; case EXC_OBJ_HOR_CENTER: eVerAlign = SDRTEXTVERTADJUST_CENTER; break; case EXC_OBJ_HOR_RIGHT: eVerAlign = SDRTEXTVERTADJUST_TOP; break; case EXC_OBJ_HOR_JUSTIFY: eVerAlign = SDRTEXTVERTADJUST_BLOCK; break; } MSO_Anchor eTextAnchor = (MSO_Anchor)rDffConv.GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop ); switch ( eTextAnchor ) { case mso_anchorTopCentered : case mso_anchorMiddleCentered : case mso_anchorBottomCentered : { eHorAlign = SVX_ADJUST_CENTER; } break; default: { switch( maTextData.maData.GetVerAlign() ) { case EXC_OBJ_VER_TOP: eHorAlign = SVX_ADJUST_LEFT; break; case EXC_OBJ_VER_CENTER: eHorAlign = SVX_ADJUST_CENTER; break; case EXC_OBJ_VER_BOTTOM: eHorAlign = SVX_ADJUST_RIGHT; break; case EXC_OBJ_VER_JUSTIFY: eHorAlign = SVX_ADJUST_BLOCK; break; } } } } break; } rSdrObj.SetMergedItem( SvxAdjustItem( eHorAlign, EE_PARA_JUST ) ); rSdrObj.SetMergedItem( SdrTextVertAdjustItem( eVerAlign ) ); rSdrObj.SetMergedItem( SvxWritingModeItem( eWriteMode, SDRATTR_TEXTDIRECTION ) ); } } // base class processing XclImpRectObj::DoPreProcessSdrObj( rDffConv, rSdrObj ); } // ---------------------------------------------------------------------------- XclImpChartObj::XclImpChartObj( const XclImpRoot& rRoot, bool bOwnTab ) : XclImpRectObj( rRoot ), mbOwnTab( bOwnTab ) { SetSimpleMacro( false ); SetCustomDffObj( true ); } void XclImpChartObj::ReadChartSubStream( XclImpStream& rStrm ) { if( mbOwnTab ? (rStrm.GetRecId() == EXC_ID5_BOF) : ((rStrm.GetNextRecId() == EXC_ID5_BOF) && rStrm.StartNextRecord()) ) { sal_uInt16 nBofType; rStrm.Seek( 2 ); rStrm >> nBofType; OSL_ENSURE( nBofType == EXC_BOF_CHART, "XclImpChartObj::ReadChartSubStream - no chart BOF record" ); // read chart, even if BOF record contains wrong substream identifier mxChart.reset( new XclImpChart( GetRoot(), mbOwnTab ) ); mxChart->ReadChartSubStream( rStrm ); if( mbOwnTab ) FinalizeTabChart(); } else { OSL_FAIL( "XclImpChartObj::ReadChartSubStream - missing chart substream" ); } } void XclImpChartObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize ) { // read OBJ record and the following chart substream ReadFrameData( rStrm ); rStrm.Ignore( 18 ); ReadMacro3( rStrm, nMacroSize ); // set frame format from OBJ record, it is used if chart itself is transparent if( mxChart ) mxChart->UpdateObjFrame( maLineData, maFillData ); } void XclImpChartObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize ) { // read OBJ record and the following chart substream ReadFrameData( rStrm ); rStrm.Ignore( 18 ); ReadMacro4( rStrm, nMacroSize ); // set frame format from OBJ record, it is used if chart itself is transparent if( mxChart ) mxChart->UpdateObjFrame( maLineData, maFillData ); } void XclImpChartObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ) { // read OBJ record and the following chart substream ReadFrameData( rStrm ); rStrm.Ignore( 18 ); ReadName5( rStrm, nNameLen ); ReadMacro5( rStrm, nMacroSize ); ReadChartSubStream( rStrm ); // set frame format from OBJ record, it is used if chart itself is transparent if( mxChart ) mxChart->UpdateObjFrame( maLineData, maFillData ); } void XclImpChartObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 /*nSubRecSize*/ ) { // read the following chart substream if( nSubRecId == EXC_ID_OBJEND ) { // enable CONTINUE handling for the entire chart substream rStrm.ResetRecord( true ); ReadChartSubStream( rStrm ); /* disable CONTINUE handling again to be able to read following CONTINUE records as MSODRAWING records. */ rStrm.ResetRecord( false ); } } sal_Size XclImpChartObj::DoGetProgressSize() const { return mxChart ? mxChart->GetProgressSize() : 1; } SdrObject* XclImpChartObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const Rectangle& rAnchorRect ) const { SdrObjectPtr xSdrObj; SfxObjectShell* pDocShell = GetDocShell(); if( rDffConv.SupportsOleObjects() && SvtModuleOptions().IsChart() && pDocShell && mxChart && !mxChart->IsPivotChart() ) { // create embedded chart object OUString aEmbObjName; Reference< XEmbeddedObject > xEmbObj = pDocShell->GetEmbeddedObjectContainer(). CreateEmbeddedObject( SvGlobalName( SO3_SCH_CLASSID ).GetByteSequence(), aEmbObjName ); /* Set the size to the embedded object, this prevents that font sizes of text objects are changed in the chart when the object is inserted into the draw page. */ sal_Int64 nAspect = ::com::sun::star::embed::Aspects::MSOLE_CONTENT; MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xEmbObj->getMapUnit( nAspect ) ); Size aSize( Window::LogicToLogic( rAnchorRect.GetSize(), MapMode( MAP_100TH_MM ), MapMode( aUnit ) ) ); ::com::sun::star::awt::Size aAwtSize( aSize.Width(), aSize.Height() ); xEmbObj->setVisualAreaSize( nAspect, aAwtSize ); // create the container OLE object xSdrObj.reset( new SdrOle2Obj( svt::EmbeddedObjectRef( xEmbObj, nAspect ), aEmbObjName, rAnchorRect ) ); } return xSdrObj.release(); } void XclImpChartObj::DoPostProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const { const SdrOle2Obj* pSdrOleObj = dynamic_cast< const SdrOle2Obj* >( &rSdrObj ); if( mxChart && pSdrOleObj ) { Reference< XEmbeddedObject > xEmbObj = pSdrOleObj->GetObjRef(); if( xEmbObj.is() && ::svt::EmbeddedObjectRef::TryRunningState( xEmbObj ) ) try { Reference< XEmbedPersist > xPersist( xEmbObj, UNO_QUERY_THROW ); Reference< XModel > xModel( xEmbObj->getComponent(), UNO_QUERY_THROW ); mxChart->Convert( xModel, rDffConv, xPersist->getEntryName(), rSdrObj.GetLogicRect() ); xPersist->storeOwn(); } catch( const Exception& ) { } } } void XclImpChartObj::FinalizeTabChart() { /* #i44077# Calculate and store DFF anchor for sheet charts. Needed to get used area if this chart is inserted as OLE object. */ OSL_ENSURE( mbOwnTab, "XclImpChartObj::FinalizeTabChart - not allowed for embedded chart objects" ); // set uninitialized page to landscape if( !GetPageSettings().GetPageData().mbValid ) GetPageSettings().SetPaperSize( EXC_PAPERSIZE_DEFAULT, false ); // calculate size of the chart object const XclPageData& rPageData = GetPageSettings().GetPageData(); Size aPaperSize = rPageData.GetScPaperSize(); long nWidth = XclTools::GetHmmFromTwips( aPaperSize.Width() ); long nHeight = XclTools::GetHmmFromTwips( aPaperSize.Height() ); // subtract page margins, give some more extra space nWidth -= (XclTools::GetHmmFromInch( rPageData.mfLeftMargin + rPageData.mfRightMargin ) + 2000); nHeight -= (XclTools::GetHmmFromInch( rPageData.mfTopMargin + rPageData.mfBottomMargin ) + 1000); // print column/row headers? if( rPageData.mbPrintHeadings ) { nWidth -= 2000; nHeight -= 1000; } // create the object anchor XclObjAnchor aAnchor; aAnchor.SetRect( GetRoot(), GetCurrScTab(), Rectangle( 1000, 500, nWidth, nHeight ), MAP_100TH_MM ); SetAnchor( aAnchor ); } // ---------------------------------------------------------------------------- XclImpNoteObj::XclImpNoteObj( const XclImpRoot& rRoot ) : XclImpTextObj( rRoot ), maScPos( ScAddress::INITIALIZE_INVALID ), mnNoteFlags( 0 ) { SetSimpleMacro( false ); // caption object will be created manually SetInsertSdrObj( false ); } void XclImpNoteObj::SetNoteData( const ScAddress& rScPos, sal_uInt16 nNoteFlags ) { maScPos = rScPos; mnNoteFlags = nNoteFlags; } void XclImpNoteObj::DoPreProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const { // create formatted text XclImpTextObj::DoPreProcessSdrObj( rDffConv, rSdrObj ); OutlinerParaObject* pOutlinerObj = rSdrObj.GetOutlinerParaObject(); if( maScPos.IsValid() && pOutlinerObj ) { // create cell note with all data from drawing object ScNoteUtil::CreateNoteFromObjectData( GetDoc(), maScPos, rSdrObj.GetMergedItemSet().Clone(), // new object on heap expected new OutlinerParaObject( *pOutlinerObj ), // new object on heap expected rSdrObj.GetLogicRect(), ::get_flag( mnNoteFlags, EXC_NOTE_VISIBLE ), false ); } } // ---------------------------------------------------------------------------- XclImpControlHelper::XclImpControlHelper( const XclImpRoot& rRoot, XclCtrlBindMode eBindMode ) : mrRoot( rRoot ), meBindMode( eBindMode ) { } XclImpControlHelper::~XclImpControlHelper() { } SdrObject* XclImpControlHelper::CreateSdrObjectFromShape( const Reference< XShape >& rxShape, const Rectangle& rAnchorRect ) const { mxShape = rxShape; SdrObjectPtr xSdrObj( SdrObject::getSdrObjectFromXShape( rxShape ) ); if( xSdrObj.is() ) { xSdrObj->NbcSetSnapRect( rAnchorRect ); // #i30543# insert into control layer xSdrObj->NbcSetLayer( SC_LAYER_CONTROLS ); } return xSdrObj.release(); } void XclImpControlHelper::ApplySheetLinkProps() const { Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( mxShape ); if( !xCtrlModel.is() ) return; ScfPropertySet aPropSet( xCtrlModel ); // sheet links if( SfxObjectShell* pDocShell = mrRoot.GetDocShell() ) { Reference< XMultiServiceFactory > xFactory( pDocShell->GetModel(), UNO_QUERY ); if( xFactory.is() ) { // cell link if( mxCellLink ) try { Reference< XBindableValue > xBindable( xCtrlModel, UNO_QUERY_THROW ); // create argument sequence for createInstanceWithArguments() CellAddress aApiAddress; ScUnoConversion::FillApiAddress( aApiAddress, *mxCellLink ); NamedValue aValue; aValue.Name = CREATE_OUSTRING( SC_UNONAME_BOUNDCELL ); aValue.Value <<= aApiAddress; Sequence< Any > aArgs( 1 ); aArgs[ 0 ] <<= aValue; // create the CellValueBinding instance and set at the control model OUString aServiceName; switch( meBindMode ) { case EXC_CTRL_BINDCONTENT: aServiceName = CREATE_OUSTRING( SC_SERVICENAME_VALBIND ); break; case EXC_CTRL_BINDPOSITION: aServiceName = CREATE_OUSTRING( SC_SERVICENAME_LISTCELLBIND ); break; } Reference< XValueBinding > xBinding( xFactory->createInstanceWithArguments( aServiceName, aArgs ), UNO_QUERY_THROW ); xBindable->setValueBinding( xBinding ); } catch( const Exception& ) { } // source range if( mxSrcRange ) try { Reference< XListEntrySink > xEntrySink( xCtrlModel, UNO_QUERY_THROW ); // create argument sequence for createInstanceWithArguments() CellRangeAddress aApiRange; ScUnoConversion::FillApiRange( aApiRange, *mxSrcRange ); NamedValue aValue; aValue.Name = CREATE_OUSTRING( SC_UNONAME_CELLRANGE ); aValue.Value <<= aApiRange; Sequence< Any > aArgs( 1 ); aArgs[ 0 ] <<= aValue; // create the EntrySource instance and set at the control model Reference< XListEntrySource > xEntrySource( xFactory->createInstanceWithArguments( CREATE_OUSTRING( SC_SERVICENAME_LISTSOURCE ), aArgs ), UNO_QUERY_THROW ); xEntrySink->setListEntrySource( xEntrySource ); } catch( const Exception& ) { } } } } void XclImpControlHelper::ProcessControl( const XclImpDrawObjBase& rDrawObj ) const { Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( mxShape ); if( !xCtrlModel.is() ) return; ApplySheetLinkProps(); ScfPropertySet aPropSet( xCtrlModel ); // #i51348# set object name at control model aPropSet.SetStringProperty( CREATE_OUSTRING( "Name" ), rDrawObj.GetObjName() ); // control visible and printable? aPropSet.SetBoolProperty( CREATE_OUSTRING( "EnableVisible" ), rDrawObj.IsVisible() ); aPropSet.SetBoolProperty( CREATE_OUSTRING( "Printable" ), rDrawObj.IsPrintable() ); // virtual call for type specific processing DoProcessControl( aPropSet ); } void XclImpControlHelper::ReadCellLinkFormula( XclImpStream& rStrm, bool bWithBoundSize ) { ScRangeList aScRanges; ReadRangeList( aScRanges, rStrm, bWithBoundSize ); // Use first cell of first range if ( !aScRanges.empty() ) { const ScRange* pScRange = aScRanges.front(); mxCellLink.reset( new ScAddress( pScRange->aStart ) ); } } void XclImpControlHelper::ReadSourceRangeFormula( XclImpStream& rStrm, bool bWithBoundSize ) { ScRangeList aScRanges; ReadRangeList( aScRanges, rStrm, bWithBoundSize ); // Use first range if ( !aScRanges.empty() ) { const ScRange* pScRange = aScRanges.front(); mxSrcRange.reset( new ScRange( *pScRange ) ); } } void XclImpControlHelper::DoProcessControl( ScfPropertySet& ) const { } void XclImpControlHelper::ReadRangeList( ScRangeList& rScRanges, XclImpStream& rStrm ) { XclTokenArray aXclTokArr; aXclTokArr.ReadSize( rStrm ); rStrm.Ignore( 4 ); aXclTokArr.ReadArray( rStrm ); mrRoot.GetFormulaCompiler().CreateRangeList( rScRanges, EXC_FMLATYPE_CONTROL, aXclTokArr, rStrm ); } void XclImpControlHelper::ReadRangeList( ScRangeList& rScRanges, XclImpStream& rStrm, bool bWithBoundSize ) { if( bWithBoundSize ) { sal_uInt16 nSize; rStrm >> nSize; if( nSize > 0 ) { rStrm.PushPosition(); ReadRangeList( rScRanges, rStrm ); rStrm.PopPosition(); rStrm.Ignore( nSize ); } } else { ReadRangeList( rScRanges, rStrm ); } } // ---------------------------------------------------------------------------- XclImpTbxObjBase::XclImpTbxObjBase( const XclImpRoot& rRoot ) : XclImpTextObj( rRoot ), XclImpControlHelper( rRoot, EXC_CTRL_BINDPOSITION ) { SetSimpleMacro( false ); SetCustomDffObj( true ); } namespace { void lclExtractColor( sal_uInt8& rnColorIdx, const DffPropSet& rDffPropSet, sal_uInt32 nPropId ) { if( rDffPropSet.IsProperty( nPropId ) ) { sal_uInt32 nColor = rDffPropSet.GetPropertyValue( nPropId ); if( (nColor & 0xFF000000) == 0x08000000 ) rnColorIdx = ::extract_value< sal_uInt8 >( nColor, 0, 8 ); } } } // namespace void XclImpTbxObjBase::SetDffProperties( const DffPropSet& rDffPropSet ) { maFillData.mnPattern = rDffPropSet.GetPropertyBool( DFF_Prop_fFilled ) ? EXC_PATT_SOLID : EXC_PATT_NONE; lclExtractColor( maFillData.mnBackColorIdx, rDffPropSet, DFF_Prop_fillBackColor ); lclExtractColor( maFillData.mnPattColorIdx, rDffPropSet, DFF_Prop_fillColor ); ::set_flag( maFillData.mnAuto, EXC_OBJ_LINE_AUTO, false ); maLineData.mnStyle = rDffPropSet.GetPropertyBool( DFF_Prop_fLine ) ? EXC_OBJ_LINE_SOLID : EXC_OBJ_LINE_NONE; lclExtractColor( maLineData.mnColorIdx, rDffPropSet, DFF_Prop_lineColor ); ::set_flag( maLineData.mnAuto, EXC_OBJ_FILL_AUTO, false ); } bool XclImpTbxObjBase::FillMacroDescriptor( ScriptEventDescriptor& rDescriptor ) const { return XclControlHelper::FillMacroDescriptor( rDescriptor, DoGetEventType(), GetMacroName(), GetDocShell() ); } void XclImpTbxObjBase::ConvertFont( ScfPropertySet& rPropSet ) const { if( maTextData.mxString ) { const XclFormatRunVec& rFormatRuns = maTextData.mxString->GetFormats(); if( rFormatRuns.empty() ) GetFontBuffer().WriteDefaultCtrlFontProperties( rPropSet ); else GetFontBuffer().WriteFontProperties( rPropSet, EXC_FONTPROPSET_CONTROL, rFormatRuns.front().mnFontIdx ); } } void XclImpTbxObjBase::ConvertLabel( ScfPropertySet& rPropSet ) const { if( maTextData.mxString ) { String aLabel = maTextData.mxString->GetText(); if( maTextData.maData.mnShortcut > 0 ) { xub_StrLen nPos = aLabel.Search( static_cast< sal_Unicode >( maTextData.maData.mnShortcut ) ); if( nPos != STRING_NOTFOUND ) aLabel.Insert( '~', nPos ); } rPropSet.SetStringProperty( CREATE_OUSTRING( "Label" ), aLabel ); } ConvertFont( rPropSet ); } SdrObject* XclImpTbxObjBase::DoCreateSdrObj( XclImpDffConverter& rDffConv, const Rectangle& rAnchorRect ) const { SdrObjectPtr xSdrObj( rDffConv.CreateSdrObject( *this, rAnchorRect ) ); rDffConv.Progress(); return xSdrObj.release(); } void XclImpTbxObjBase::DoPreProcessSdrObj( XclImpDffConverter& /*rDffConv*/, SdrObject& /*rSdrObj*/ ) const { // do not call DoPreProcessSdrObj() from base class (to skip text processing) ProcessControl( *this ); } // ---------------------------------------------------------------------------- XclImpButtonObj::XclImpButtonObj( const XclImpRoot& rRoot ) : XclImpTbxObjBase( rRoot ) { } void XclImpButtonObj::DoProcessControl( ScfPropertySet& rPropSet ) const { // label and text formatting ConvertLabel( rPropSet ); /* Horizontal text alignment. For unknown reason, the property type is a simple sal_Int16 and not a com.sun.star.style.HorizontalAlignment. */ sal_Int16 nHorAlign = 1; switch( maTextData.maData.GetHorAlign() ) { case EXC_OBJ_HOR_LEFT: nHorAlign = 0; break; case EXC_OBJ_HOR_CENTER: nHorAlign = 1; break; case EXC_OBJ_HOR_RIGHT: nHorAlign = 2; break; } rPropSet.SetProperty( CREATE_OUSTRING( "Align" ), nHorAlign ); // vertical text alignment namespace csss = ::com::sun::star::style; csss::VerticalAlignment eVerAlign = csss::VerticalAlignment_MIDDLE; switch( maTextData.maData.GetVerAlign() ) { case EXC_OBJ_VER_TOP: eVerAlign = csss::VerticalAlignment_TOP; break; case EXC_OBJ_VER_CENTER: eVerAlign = csss::VerticalAlignment_MIDDLE; break; case EXC_OBJ_VER_BOTTOM: eVerAlign = csss::VerticalAlignment_BOTTOM; break; } rPropSet.SetProperty( CREATE_OUSTRING( "VerticalAlign" ), eVerAlign ); // always wrap text automatically rPropSet.SetBoolProperty( CREATE_OUSTRING( "MultiLine" ), true ); // default button bool bDefButton = ::get_flag( maTextData.maData.mnButtonFlags, EXC_OBJ_BUTTON_DEFAULT ); rPropSet.SetBoolProperty( CREATE_OUSTRING( "DefaultButton" ), bDefButton ); // button type (flags cannot be combined in OOo) namespace cssa = ::com::sun::star::awt; cssa::PushButtonType eButtonType = cssa::PushButtonType_STANDARD; if( ::get_flag( maTextData.maData.mnButtonFlags, EXC_OBJ_BUTTON_CLOSE ) ) eButtonType = cssa::PushButtonType_OK; else if( ::get_flag( maTextData.maData.mnButtonFlags, EXC_OBJ_BUTTON_CANCEL ) ) eButtonType = cssa::PushButtonType_CANCEL; else if( ::get_flag( maTextData.maData.mnButtonFlags, EXC_OBJ_BUTTON_HELP ) ) eButtonType = cssa::PushButtonType_HELP; // property type is short, not enum rPropSet.SetProperty( CREATE_OUSTRING( "PushButtonType" ), sal_Int16( eButtonType ) ); } OUString XclImpButtonObj::DoGetServiceName() const { return CREATE_OUSTRING( "com.sun.star.form.component.CommandButton" ); } XclTbxEventType XclImpButtonObj::DoGetEventType() const { return EXC_TBX_EVENT_ACTION; } // ---------------------------------------------------------------------------- XclImpCheckBoxObj::XclImpCheckBoxObj( const XclImpRoot& rRoot ) : XclImpTbxObjBase( rRoot ), mnState( EXC_OBJ_CHECKBOX_UNCHECKED ), mnCheckBoxFlags( 0 ) { } void XclImpCheckBoxObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ ) { ReadFrameData( rStrm ); rStrm.Ignore( 10 ); rStrm >> maTextData.maData.mnFlags; rStrm.Ignore( 20 ); ReadName5( rStrm, nNameLen ); ReadMacro5( rStrm, rStrm.ReaduInt16() ); // fist macro size invalid and unused ReadCellLinkFormula( rStrm, true ); rStrm >> maTextData.maData.mnTextLen; maTextData.ReadByteString( rStrm ); rStrm >> mnState >> maTextData.maData.mnShortcut >> maTextData.maData.mnShortcutEA >> mnCheckBoxFlags; } void XclImpCheckBoxObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize ) { switch( nSubRecId ) { case EXC_ID_OBJCBLS: // do not read EXC_ID_OBJCBLSDATA, not written by OOo Excel export rStrm >> mnState; rStrm.Ignore( 4 ); rStrm >> maTextData.maData.mnShortcut >> maTextData.maData.mnShortcutEA >> mnCheckBoxFlags; break; case EXC_ID_OBJCBLSFMLA: ReadCellLinkFormula( rStrm, false ); break; default: XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize ); } } void XclImpCheckBoxObj::DoProcessControl( ScfPropertySet& rPropSet ) const { // label and text formatting ConvertLabel( rPropSet ); // state bool bSupportsTristate = GetObjType() == EXC_OBJTYPE_CHECKBOX; sal_Int16 nApiState = 0; switch( mnState ) { case EXC_OBJ_CHECKBOX_UNCHECKED: nApiState = 0; break; case EXC_OBJ_CHECKBOX_CHECKED: nApiState = 1; break; case EXC_OBJ_CHECKBOX_TRISTATE: nApiState = bSupportsTristate ? 2 : 1; break; } if( bSupportsTristate ) rPropSet.SetBoolProperty( CREATE_OUSTRING( "TriState" ), nApiState == 2 ); rPropSet.SetProperty( CREATE_OUSTRING( "DefaultState" ), nApiState ); // box style namespace AwtVisualEffect = ::com::sun::star::awt::VisualEffect; sal_Int16 nEffect = ::get_flagvalue( mnCheckBoxFlags, EXC_OBJ_CHECKBOX_FLAT, AwtVisualEffect::FLAT, AwtVisualEffect::LOOK3D ); rPropSet.SetProperty( CREATE_OUSTRING( "VisualEffect" ), nEffect ); // do not wrap text automatically rPropSet.SetBoolProperty( CREATE_OUSTRING( "MultiLine" ), false ); // #i40279# always centered vertically namespace csss = ::com::sun::star::style; rPropSet.SetProperty( CREATE_OUSTRING( "VerticalAlign" ), csss::VerticalAlignment_MIDDLE ); // background color if( maFillData.IsFilled() ) { sal_Int32 nColor = static_cast< sal_Int32 >( GetSolidFillColor( maFillData ).GetColor() ); rPropSet.SetProperty( CREATE_OUSTRING( "BackgroundColor" ), nColor ); } } OUString XclImpCheckBoxObj::DoGetServiceName() const { return CREATE_OUSTRING( "com.sun.star.form.component.CheckBox" ); } XclTbxEventType XclImpCheckBoxObj::DoGetEventType() const { return EXC_TBX_EVENT_ACTION; } // ---------------------------------------------------------------------------- XclImpOptionButtonObj::XclImpOptionButtonObj( const XclImpRoot& rRoot ) : XclImpCheckBoxObj( rRoot ), mnNextInGroup( 0 ), mnFirstInGroup( 1 ) { } void XclImpOptionButtonObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ ) { ReadFrameData( rStrm ); rStrm.Ignore( 10 ); rStrm >> maTextData.maData.mnFlags; rStrm.Ignore( 32 ); ReadName5( rStrm, nNameLen ); ReadMacro5( rStrm, rStrm.ReaduInt16() ); // fist macro size invalid and unused ReadCellLinkFormula( rStrm, true ); rStrm >> maTextData.maData.mnTextLen; maTextData.ReadByteString( rStrm ); rStrm >> mnState >> maTextData.maData.mnShortcut >> maTextData.maData.mnShortcutEA; rStrm >> mnCheckBoxFlags >> mnNextInGroup >> mnFirstInGroup; } void XclImpOptionButtonObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize ) { switch( nSubRecId ) { case EXC_ID_OBJRBODATA: rStrm >> mnNextInGroup >> mnFirstInGroup; break; default: XclImpCheckBoxObj::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize ); } } void XclImpOptionButtonObj::DoProcessControl( ScfPropertySet& rPropSet ) const { XclImpCheckBoxObj::DoProcessControl( rPropSet ); // TODO: grouping XclImpOptionButtonObj* pTbxObj = dynamic_cast< XclImpOptionButtonObj* >( GetObjectManager().GetSheetDrawing( GetTab() ).FindDrawObj( mnNextInGroup ).get() ); if ( ( pTbxObj && pTbxObj->mnFirstInGroup ) ) { // Group has terminated // traverse each RadioButton in group and // a) apply the groupname // b) propagate the linked cell from the lead radiobutton // c) apply the correct Ref value XclImpOptionButtonObj* pLeader = pTbxObj; ; sal_Int32 nRefVal = 1; OSL_TRACE( "0x%x start group ", pLeader->GetObjId()/*.mnObjId */); do { Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( pTbxObj->mxShape ); if ( xCtrlModel.is() ) { ScfPropertySet aProps( xCtrlModel ); rtl::OUString sGroupName = rtl::OUString::valueOf( static_cast< sal_Int32 >( pLeader->GetDffShapeId() ) ); aProps.SetStringProperty( CREATE_OUSTRING( "GroupName" ), sGroupName ); aProps.SetStringProperty( CREATE_OUSTRING( "RefValue" ), rtl::OUString::valueOf( nRefVal++ ) ); if ( pLeader->HasCellLink() && !pTbxObj->HasCellLink() ) { // propagate cell link info pTbxObj->mxCellLink.reset( new ScAddress( *pLeader->mxCellLink.get() ) ); pTbxObj->ApplySheetLinkProps(); } pTbxObj = dynamic_cast< XclImpOptionButtonObj* >( GetObjectManager().GetSheetDrawing( GetTab() ).FindDrawObj( pTbxObj->mnNextInGroup ).get() ); } else pTbxObj = NULL; } while ( pTbxObj && !( pTbxObj->mnFirstInGroup == 1 ) ); } else { // not the leader? try and find it } } OUString XclImpOptionButtonObj::DoGetServiceName() const { return CREATE_OUSTRING( "com.sun.star.form.component.RadioButton" ); } XclTbxEventType XclImpOptionButtonObj::DoGetEventType() const { return EXC_TBX_EVENT_ACTION; } // ---------------------------------------------------------------------------- XclImpLabelObj::XclImpLabelObj( const XclImpRoot& rRoot ) : XclImpTbxObjBase( rRoot ) { } void XclImpLabelObj::DoProcessControl( ScfPropertySet& rPropSet ) const { // label and text formatting ConvertLabel( rPropSet ); // text alignment (always top/left aligned) rPropSet.SetProperty( CREATE_OUSTRING( "Align" ), sal_Int16( 0 ) ); namespace csss = ::com::sun::star::style; rPropSet.SetProperty( CREATE_OUSTRING( "VerticalAlign" ), csss::VerticalAlignment_TOP ); // always wrap text automatically rPropSet.SetBoolProperty( CREATE_OUSTRING( "MultiLine" ), true ); } OUString XclImpLabelObj::DoGetServiceName() const { return CREATE_OUSTRING( "com.sun.star.form.component.FixedText" ); } XclTbxEventType XclImpLabelObj::DoGetEventType() const { return EXC_TBX_EVENT_MOUSE; } // ---------------------------------------------------------------------------- XclImpGroupBoxObj::XclImpGroupBoxObj( const XclImpRoot& rRoot ) : XclImpTbxObjBase( rRoot ), mnGroupBoxFlags( 0 ) { } void XclImpGroupBoxObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ ) { ReadFrameData( rStrm ); rStrm.Ignore( 10 ); rStrm >> maTextData.maData.mnFlags; rStrm.Ignore( 26 ); ReadName5( rStrm, nNameLen ); ReadMacro5( rStrm, rStrm.ReaduInt16() ); // fist macro size invalid and unused rStrm >> maTextData.maData.mnTextLen; maTextData.ReadByteString( rStrm ); rStrm >> maTextData.maData.mnShortcut >> maTextData.maData.mnShortcutEA >> mnGroupBoxFlags; } void XclImpGroupBoxObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize ) { switch( nSubRecId ) { case EXC_ID_OBJGBODATA: rStrm >> maTextData.maData.mnShortcut >> maTextData.maData.mnShortcutEA >> mnGroupBoxFlags; break; default: XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize ); } } void XclImpGroupBoxObj::DoProcessControl( ScfPropertySet& rPropSet ) const { // label and text formatting ConvertLabel( rPropSet ); } OUString XclImpGroupBoxObj::DoGetServiceName() const { return CREATE_OUSTRING( "com.sun.star.form.component.GroupBox" ); } XclTbxEventType XclImpGroupBoxObj::DoGetEventType() const { return EXC_TBX_EVENT_MOUSE; } // ---------------------------------------------------------------------------- XclImpDialogObj::XclImpDialogObj( const XclImpRoot& rRoot ) : XclImpTbxObjBase( rRoot ) { } void XclImpDialogObj::DoProcessControl( ScfPropertySet& rPropSet ) const { // label and text formatting ConvertLabel( rPropSet ); } OUString XclImpDialogObj::DoGetServiceName() const { // dialog frame faked by a groupbox return CREATE_OUSTRING( "com.sun.star.form.component.GroupBox" ); } XclTbxEventType XclImpDialogObj::DoGetEventType() const { return EXC_TBX_EVENT_MOUSE; } // ---------------------------------------------------------------------------- XclImpEditObj::XclImpEditObj( const XclImpRoot& rRoot ) : XclImpTbxObjBase( rRoot ), mnContentType( EXC_OBJ_EDIT_TEXT ), mnMultiLine( 0 ), mnScrollBar( 0 ), mnListBoxObjId( 0 ) { } bool XclImpEditObj::IsNumeric() const { return (mnContentType == EXC_OBJ_EDIT_INTEGER) || (mnContentType == EXC_OBJ_EDIT_DOUBLE); } void XclImpEditObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ ) { ReadFrameData( rStrm ); rStrm.Ignore( 10 ); rStrm >> maTextData.maData.mnFlags; rStrm.Ignore( 14 ); ReadName5( rStrm, nNameLen ); ReadMacro5( rStrm, rStrm.ReaduInt16() ); // fist macro size invalid and unused rStrm >> maTextData.maData.mnTextLen; maTextData.ReadByteString( rStrm ); rStrm >> mnContentType >> mnMultiLine >> mnScrollBar >> mnListBoxObjId; } void XclImpEditObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize ) { switch( nSubRecId ) { case EXC_ID_OBJEDODATA: rStrm >> mnContentType >> mnMultiLine >> mnScrollBar >> mnListBoxObjId; break; default: XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize ); } } void XclImpEditObj::DoProcessControl( ScfPropertySet& rPropSet ) const { if( maTextData.mxString ) { OUString aText = maTextData.mxString->GetText(); if( IsNumeric() ) { // TODO: OUString::toDouble() does not handle local decimal separator rPropSet.SetProperty( CREATE_OUSTRING( "DefaultValue" ), aText.toDouble() ); rPropSet.SetBoolProperty( CREATE_OUSTRING( "Spin" ), mnScrollBar != 0 ); } else { rPropSet.SetProperty( CREATE_OUSTRING( "DefaultText" ), aText ); rPropSet.SetBoolProperty( CREATE_OUSTRING( "MultiLine" ), mnMultiLine != 0 ); rPropSet.SetBoolProperty( CREATE_OUSTRING( "VScroll" ), mnScrollBar != 0 ); } } ConvertFont( rPropSet ); } OUString XclImpEditObj::DoGetServiceName() const { return IsNumeric() ? CREATE_OUSTRING( "com.sun.star.form.component.NumericField" ) : CREATE_OUSTRING( "com.sun.star.form.component.TextField" ); } XclTbxEventType XclImpEditObj::DoGetEventType() const { return EXC_TBX_EVENT_TEXT; } // ---------------------------------------------------------------------------- XclImpTbxObjScrollableBase::XclImpTbxObjScrollableBase( const XclImpRoot& rRoot ) : XclImpTbxObjBase( rRoot ), mnValue( 0 ), mnMin( 0 ), mnMax( 100 ), mnStep( 1 ), mnPageStep( 10 ), mnOrient( 0 ), mnThumbWidth( 1 ), mnScrollFlags( 0 ) { } void XclImpTbxObjScrollableBase::ReadSbs( XclImpStream& rStrm ) { rStrm.Ignore( 4 ); rStrm >> mnValue >> mnMin >> mnMax >> mnStep >> mnPageStep >> mnOrient >> mnThumbWidth >> mnScrollFlags; } void XclImpTbxObjScrollableBase::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize ) { switch( nSubRecId ) { case EXC_ID_OBJSBS: ReadSbs( rStrm ); break; case EXC_ID_OBJSBSFMLA: ReadCellLinkFormula( rStrm, false ); break; default: XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize ); } } // ---------------------------------------------------------------------------- XclImpSpinButtonObj::XclImpSpinButtonObj( const XclImpRoot& rRoot ) : XclImpTbxObjScrollableBase( rRoot ) { } void XclImpSpinButtonObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ ) { ReadFrameData( rStrm ); ReadSbs( rStrm ); ReadName5( rStrm, nNameLen ); ReadMacro5( rStrm, rStrm.ReaduInt16() ); // fist macro size invalid and unused ReadCellLinkFormula( rStrm, true ); } void XclImpSpinButtonObj::DoProcessControl( ScfPropertySet& rPropSet ) const { // Calc's "Border" property is not the 3D/flat style effect in Excel (#i34712#) rPropSet.SetProperty( CREATE_OUSTRING( "Border" ), ::com::sun::star::awt::VisualEffect::NONE ); rPropSet.SetProperty< sal_Int32 >( CREATE_OUSTRING( "DefaultSpinValue" ), mnValue ); rPropSet.SetProperty< sal_Int32 >( CREATE_OUSTRING( "SpinValueMin" ), mnMin ); rPropSet.SetProperty< sal_Int32 >( CREATE_OUSTRING( "SpinValueMax" ), mnMax ); rPropSet.SetProperty< sal_Int32 >( CREATE_OUSTRING( "SpinIncrement" ), mnStep ); // Excel spin buttons always vertical rPropSet.SetProperty( CREATE_OUSTRING( "Orientation" ), ::com::sun::star::awt::ScrollBarOrientation::VERTICAL ); } OUString XclImpSpinButtonObj::DoGetServiceName() const { return CREATE_OUSTRING( "com.sun.star.form.component.SpinButton" ); } XclTbxEventType XclImpSpinButtonObj::DoGetEventType() const { return EXC_TBX_EVENT_VALUE; } // ---------------------------------------------------------------------------- XclImpScrollBarObj::XclImpScrollBarObj( const XclImpRoot& rRoot ) : XclImpTbxObjScrollableBase( rRoot ) { } void XclImpScrollBarObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ ) { ReadFrameData( rStrm ); ReadSbs( rStrm ); ReadName5( rStrm, nNameLen ); ReadMacro5( rStrm, rStrm.ReaduInt16() ); // fist macro size invalid and unused ReadCellLinkFormula( rStrm, true ); } void XclImpScrollBarObj::DoProcessControl( ScfPropertySet& rPropSet ) const { // Calc's "Border" property is not the 3D/flat style effect in Excel (#i34712#) rPropSet.SetProperty( CREATE_OUSTRING( "Border" ), ::com::sun::star::awt::VisualEffect::NONE ); rPropSet.SetProperty< sal_Int32 >( CREATE_OUSTRING( "DefaultScrollValue" ), mnValue ); rPropSet.SetProperty< sal_Int32 >( CREATE_OUSTRING( "ScrollValueMin" ), mnMin ); rPropSet.SetProperty< sal_Int32 >( CREATE_OUSTRING( "ScrollValueMax" ), mnMax ); rPropSet.SetProperty< sal_Int32 >( CREATE_OUSTRING( "LineIncrement" ), mnStep ); rPropSet.SetProperty< sal_Int32 >( CREATE_OUSTRING( "BlockIncrement" ), mnPageStep ); rPropSet.SetProperty( CREATE_OUSTRING( "VisibleSize" ), ::std::min< sal_Int32 >( mnPageStep, 1 ) ); namespace AwtScrollOrient = ::com::sun::star::awt::ScrollBarOrientation; sal_Int32 nApiOrient = ::get_flagvalue( mnOrient, EXC_OBJ_SCROLLBAR_HOR, AwtScrollOrient::HORIZONTAL, AwtScrollOrient::VERTICAL ); rPropSet.SetProperty( CREATE_OUSTRING( "Orientation" ), nApiOrient ); } OUString XclImpScrollBarObj::DoGetServiceName() const { return CREATE_OUSTRING( "com.sun.star.form.component.ScrollBar" ); } XclTbxEventType XclImpScrollBarObj::DoGetEventType() const { return EXC_TBX_EVENT_VALUE; } // ---------------------------------------------------------------------------- XclImpTbxObjListBase::XclImpTbxObjListBase( const XclImpRoot& rRoot ) : XclImpTbxObjScrollableBase( rRoot ), mnEntryCount( 0 ), mnSelEntry( 0 ), mnListFlags( 0 ), mnEditObjId( 0 ), mbHasDefFontIdx( false ) { } void XclImpTbxObjListBase::ReadLbsData( XclImpStream& rStrm ) { ReadSourceRangeFormula( rStrm, true ); rStrm >> mnEntryCount >> mnSelEntry >> mnListFlags >> mnEditObjId; } void XclImpTbxObjListBase::SetBoxFormatting( ScfPropertySet& rPropSet ) const { // border style namespace AwtVisualEffect = ::com::sun::star::awt::VisualEffect; sal_Int16 nApiBorder = ::get_flagvalue( mnListFlags, EXC_OBJ_LISTBOX_FLAT, AwtVisualEffect::FLAT, AwtVisualEffect::LOOK3D ); rPropSet.SetProperty( CREATE_OUSTRING( "Border" ), nApiBorder ); // font formatting if( mbHasDefFontIdx ) GetFontBuffer().WriteFontProperties( rPropSet, EXC_FONTPROPSET_CONTROL, maTextData.maData.mnDefFontIdx ); else GetFontBuffer().WriteDefaultCtrlFontProperties( rPropSet ); } // ---------------------------------------------------------------------------- XclImpListBoxObj::XclImpListBoxObj( const XclImpRoot& rRoot ) : XclImpTbxObjListBase( rRoot ) { } void XclImpListBoxObj::ReadFullLbsData( XclImpStream& rStrm, sal_Size nRecLeft ) { sal_Size nRecEnd = rStrm.GetRecPos() + nRecLeft; ReadLbsData( rStrm ); OSL_ENSURE( (rStrm.GetRecPos() == nRecEnd) || (rStrm.GetRecPos() + mnEntryCount == nRecEnd), "XclImpListBoxObj::ReadFullLbsData - invalid size of OBJLBSDATA record" ); while( rStrm.IsValid() && (rStrm.GetRecPos() < nRecEnd) ) maSelection.push_back( rStrm.ReaduInt8() ); } void XclImpListBoxObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ ) { ReadFrameData( rStrm ); ReadSbs( rStrm ); rStrm.Ignore( 18 ); rStrm >> maTextData.maData.mnDefFontIdx; rStrm.Ignore( 4 ); ReadName5( rStrm, nNameLen ); ReadMacro5( rStrm, rStrm.ReaduInt16() ); // fist macro size invalid and unused ReadCellLinkFormula( rStrm, true ); ReadFullLbsData( rStrm, rStrm.GetRecLeft() ); mbHasDefFontIdx = true; } void XclImpListBoxObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize ) { switch( nSubRecId ) { case EXC_ID_OBJLBSDATA: ReadFullLbsData( rStrm, nSubRecSize ); break; default: XclImpTbxObjListBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize ); } } void XclImpListBoxObj::DoProcessControl( ScfPropertySet& rPropSet ) const { // listbox formatting SetBoxFormatting( rPropSet ); // selection type sal_uInt8 nSelType = ::extract_value< sal_uInt8 >( mnListFlags, 4, 2 ); bool bMultiSel = nSelType != EXC_OBJ_LISTBOX_SINGLE; rPropSet.SetBoolProperty( CREATE_OUSTRING( "MultiSelection" ), bMultiSel ); // selection (do not set, if listbox is linked to a cell) if( !HasCellLink() ) { ScfInt16Vec aSelVec; // multi selection: API expects sequence of list entry indexes if( bMultiSel ) { for( ScfUInt8Vec::const_iterator aBeg = maSelection.begin(), aIt = aBeg, aEnd = maSelection.end(); aIt != aEnd; ++aIt ) if( *aIt != 0 ) aSelVec.push_back( static_cast< sal_Int16 >( aIt - aBeg ) ); } // single selection: mnSelEntry is one-based, API expects zero-based else if( mnSelEntry > 0 ) aSelVec.push_back( static_cast< sal_Int16 >( mnSelEntry - 1 ) ); if( !aSelVec.empty() ) { Sequence< sal_Int16 > aSelSeq( &aSelVec.front(), static_cast< sal_Int32 >( aSelVec.size() ) ); rPropSet.SetProperty( CREATE_OUSTRING( "DefaultSelection" ), aSelSeq ); } } } OUString XclImpListBoxObj::DoGetServiceName() const { return CREATE_OUSTRING( "com.sun.star.form.component.ListBox" ); } XclTbxEventType XclImpListBoxObj::DoGetEventType() const { return EXC_TBX_EVENT_CHANGE; } // ---------------------------------------------------------------------------- XclImpDropDownObj::XclImpDropDownObj( const XclImpRoot& rRoot ) : XclImpTbxObjListBase( rRoot ), mnLeft( 0 ), mnTop( 0 ), mnRight( 0 ), mnBottom( 0 ), mnDropDownFlags( 0 ), mnLineCount( 0 ), mnMinWidth( 0 ) { } sal_uInt16 XclImpDropDownObj::GetDropDownType() const { return ::extract_value< sal_uInt8 >( mnDropDownFlags, 0, 2 ); } void XclImpDropDownObj::ReadFullLbsData( XclImpStream& rStrm ) { ReadLbsData( rStrm ); rStrm >> mnDropDownFlags >> mnLineCount >> mnMinWidth >> maTextData.maData.mnTextLen; maTextData.ReadByteString( rStrm ); // dropdowns of auto-filters have 'simple' style, they don't have a text area if( GetDropDownType() == EXC_OBJ_DROPDOWN_SIMPLE ) SetProcessSdrObj( false ); } void XclImpDropDownObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ ) { ReadFrameData( rStrm ); ReadSbs( rStrm ); rStrm.Ignore( 18 ); rStrm >> maTextData.maData.mnDefFontIdx; rStrm.Ignore( 14 ); rStrm >> mnLeft >> mnTop >> mnRight >> mnBottom; rStrm.Ignore( 4 ); ReadName5( rStrm, nNameLen ); ReadMacro5( rStrm, rStrm.ReaduInt16() ); // fist macro size invalid and unused ReadCellLinkFormula( rStrm, true ); ReadFullLbsData( rStrm ); mbHasDefFontIdx = true; } void XclImpDropDownObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize ) { switch( nSubRecId ) { case EXC_ID_OBJLBSDATA: ReadFullLbsData( rStrm ); break; default: XclImpTbxObjListBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize ); } } void XclImpDropDownObj::DoProcessControl( ScfPropertySet& rPropSet ) const { // dropdown listbox formatting SetBoxFormatting( rPropSet ); // enable dropdown button rPropSet.SetBoolProperty( CREATE_OUSTRING( "Dropdown" ), true ); // dropdown line count rPropSet.SetProperty( CREATE_OUSTRING( "LineCount" ), mnLineCount ); if( GetDropDownType() == EXC_OBJ_DROPDOWN_COMBOBOX ) { // text of editable combobox if( maTextData.mxString ) rPropSet.SetStringProperty( CREATE_OUSTRING( "DefaultText" ), maTextData.mxString->GetText() ); } else { // selection (do not set, if dropdown is linked to a cell) if( !HasCellLink() && (mnSelEntry > 0) ) { Sequence< sal_Int16 > aSelSeq( 1 ); aSelSeq[ 0 ] = mnSelEntry - 1; rPropSet.SetProperty( CREATE_OUSTRING( "DefaultSelection" ), aSelSeq ); } } } OUString XclImpDropDownObj::DoGetServiceName() const { return (GetDropDownType() == EXC_OBJ_DROPDOWN_COMBOBOX) ? CREATE_OUSTRING( "com.sun.star.form.component.ComboBox" ) : CREATE_OUSTRING( "com.sun.star.form.component.ListBox" ); } XclTbxEventType XclImpDropDownObj::DoGetEventType() const { return (GetDropDownType() == EXC_OBJ_DROPDOWN_COMBOBOX) ? EXC_TBX_EVENT_TEXT : EXC_TBX_EVENT_CHANGE; } // ---------------------------------------------------------------------------- XclImpPictureObj::XclImpPictureObj( const XclImpRoot& rRoot ) : XclImpRectObj( rRoot ), XclImpControlHelper( rRoot, EXC_CTRL_BINDCONTENT ), mnStorageId( 0 ), mnCtlsStrmPos( 0 ), mnCtlsStrmSize( 0 ), mbEmbedded( false ), mbLinked( false ), mbSymbol( false ), mbControl( false ), mbUseCtlsStrm( false ) { SetAreaObj( true ); SetSimpleMacro( false ); SetCustomDffObj( true ); } String XclImpPictureObj::GetOleStorageName() const { String aStrgName; if( (mbEmbedded || mbLinked) && !mbControl && (mnStorageId > 0) ) { aStrgName = mbEmbedded ? EXC_STORAGE_OLE_EMBEDDED : EXC_STORAGE_OLE_LINKED; static const sal_Char spcHexChars[] = "0123456789ABCDEF"; for( sal_uInt8 nIndex = 32; nIndex > 0; nIndex -= 4 ) aStrgName.Append( sal_Unicode( spcHexChars[ ::extract_value< sal_uInt8 >( mnStorageId, nIndex - 4, 4 ) ] ) ); } return aStrgName; } void XclImpPictureObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize ) { sal_uInt16 nLinkSize; ReadFrameData( rStrm ); rStrm.Ignore( 6 ); rStrm >> nLinkSize; rStrm.Ignore( 2 ); ReadFlags3( rStrm ); ReadMacro3( rStrm, nMacroSize ); ReadPictFmla( rStrm, nLinkSize ); if( (rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord() ) maGraphic = XclImpDrawing::ReadImgData( GetRoot(), rStrm ); } void XclImpPictureObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize ) { sal_uInt16 nLinkSize; ReadFrameData( rStrm ); rStrm.Ignore( 6 ); rStrm >> nLinkSize; rStrm.Ignore( 2 ); ReadFlags3( rStrm ); ReadMacro4( rStrm, nMacroSize ); ReadPictFmla( rStrm, nLinkSize ); if( (rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord() ) maGraphic = XclImpDrawing::ReadImgData( GetRoot(), rStrm ); } void XclImpPictureObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ) { sal_uInt16 nLinkSize; ReadFrameData( rStrm ); rStrm.Ignore( 6 ); rStrm >> nLinkSize; rStrm.Ignore( 2 ); ReadFlags3( rStrm ); rStrm.Ignore( 4 ); ReadName5( rStrm, nNameLen ); ReadMacro5( rStrm, nMacroSize ); ReadPictFmla( rStrm, nLinkSize ); if( (rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord() ) { // page background is stored as hidden picture with name "__BkgndObj" if ( IsHidden() && (GetObjName() == "__BkgndObj") ) GetPageSettings().ReadImgData( rStrm ); else maGraphic = XclImpDrawing::ReadImgData( GetRoot(), rStrm ); } } void XclImpPictureObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize ) { switch( nSubRecId ) { case EXC_ID_OBJFLAGS: ReadFlags8( rStrm ); break; case EXC_ID_OBJPICTFMLA: ReadPictFmla( rStrm, rStrm.ReaduInt16() ); break; default: XclImpDrawObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize ); } } SdrObject* XclImpPictureObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const Rectangle& rAnchorRect ) const { // try to create an OLE object or form control SdrObjectPtr xSdrObj( rDffConv.CreateSdrObject( *this, rAnchorRect ) ); // insert a graphic replacement for unsupported ole object ( if none already // exists ) Hmm ok, it's possibly that there has been some imported // graphic at a base level but unlikely, normally controls have a valid // preview in the IMGDATA record ( see below ) // It might be possible to push such an imported graphic up to this // XclImpPictureObj instance but there are somany layers of indirection I // don't see an easy way. This way at least ensures that we can // avoid a 'blank' shape that can result from a failed control import if ( !xSdrObj && IsOcxControl() && maGraphic.GetType() == GRAPHIC_NONE ) { Graphic aReplacement( SdrOle2Obj::GetEmtyOLEReplacementBitmap() ); const_cast< XclImpPictureObj* >( this )->maGraphic = aReplacement; } // no OLE - create a plain picture from IMGDATA record data if( !xSdrObj && (maGraphic.GetType() != GRAPHIC_NONE) ) { xSdrObj.reset( new SdrGrafObj( maGraphic, rAnchorRect ) ); ConvertRectStyle( *xSdrObj ); } rDffConv.Progress(); return xSdrObj.release(); } OUString XclImpPictureObj::GetObjName() const { if( IsOcxControl() ) { OUString sName( GetObjectManager().GetOleNameOverride( GetTab(), GetObjId() ) ); if (!sName.isEmpty()) return sName; } return XclImpDrawObjBase::GetObjName(); } void XclImpPictureObj::DoPreProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const { if( IsOcxControl() ) { // do not call XclImpRectObj::DoPreProcessSdrObj(), it would trace missing "printable" feature ProcessControl( *this ); } else if( mbEmbedded || mbLinked ) { // trace missing "printable" feature XclImpRectObj::DoPreProcessSdrObj( rDffConv, rSdrObj ); SfxObjectShell* pDocShell = GetDocShell(); SdrOle2Obj* pOleSdrObj = dynamic_cast< SdrOle2Obj* >( &rSdrObj ); if( pOleSdrObj && pDocShell ) { comphelper::EmbeddedObjectContainer& rEmbObjCont = pDocShell->GetEmbeddedObjectContainer(); Reference< XEmbeddedObject > xEmbObj = pOleSdrObj->GetObjRef(); OUString aOldName( pOleSdrObj->GetPersistName() ); /* The object persistence should be already in the storage, but the object still might not be inserted into the container. */ if( rEmbObjCont.HasEmbeddedObject( aOldName ) ) { if( !rEmbObjCont.HasEmbeddedObject( xEmbObj ) ) // filter code is allowed to call the following method rEmbObjCont.AddEmbeddedObject( xEmbObj, aOldName ); } else { /* If the object is still not in container it must be inserted there, the name must be generated in this case. */ OUString aNewName; rEmbObjCont.InsertEmbeddedObject( xEmbObj, aNewName ); if( aOldName != aNewName ) // SetPersistName, not SetName pOleSdrObj->SetPersistName( aNewName ); } } } } void XclImpPictureObj::ReadFlags3( XclImpStream& rStrm ) { sal_uInt16 nFlags; rStrm >> nFlags; mbSymbol = ::get_flag( nFlags, EXC_OBJ_PIC_SYMBOL ); } void XclImpPictureObj::ReadFlags8( XclImpStream& rStrm ) { sal_uInt16 nFlags; rStrm >> nFlags; mbSymbol = ::get_flag( nFlags, EXC_OBJ_PIC_SYMBOL ); mbControl = ::get_flag( nFlags, EXC_OBJ_PIC_CONTROL ); mbUseCtlsStrm = ::get_flag( nFlags, EXC_OBJ_PIC_CTLSSTREAM ); OSL_ENSURE( mbControl || !mbUseCtlsStrm, "XclImpPictureObj::ReadFlags8 - CTLS stream for controls only" ); SetProcessSdrObj( mbControl || !mbUseCtlsStrm ); } void XclImpPictureObj::ReadPictFmla( XclImpStream& rStrm, sal_uInt16 nLinkSize ) { sal_Size nLinkEnd = rStrm.GetRecPos() + nLinkSize; if( nLinkSize >= 6 ) { sal_uInt16 nFmlaSize; rStrm >> nFmlaSize; OSL_ENSURE( nFmlaSize > 0, "XclImpPictureObj::ReadPictFmla - missing link formula" ); // BIFF3/BIFF4 do not support storages, nothing to do here if( (nFmlaSize > 0) && (GetBiff() >= EXC_BIFF5) ) { rStrm.Ignore( 4 ); sal_uInt8 nToken; rStrm >> nToken; // different processing for linked vs. embedded OLE objects if( nToken == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ) ) { mbLinked = true; switch( GetBiff() ) { case EXC_BIFF5: { sal_Int16 nRefIdx; sal_uInt16 nNameIdx; rStrm >> nRefIdx; rStrm.Ignore( 8 ); rStrm >> nNameIdx; rStrm.Ignore( 12 ); const ExtName* pExtName = GetOldRoot().pExtNameBuff->GetNameByIndex( nRefIdx, nNameIdx ); if( pExtName && pExtName->IsOLE() ) mnStorageId = pExtName->nStorageId; } break; case EXC_BIFF8: { sal_uInt16 nXti, nExtName; rStrm >> nXti >> nExtName; const XclImpExtName* pExtName = GetLinkManager().GetExternName( nXti, nExtName ); if( pExtName && (pExtName->GetType() == xlExtOLE) ) mnStorageId = pExtName->GetStorageId(); } break; default: DBG_ERROR_BIFF(); } } else if( nToken == XclTokenArrayHelper::GetTokenId( EXC_TOKID_TBL, EXC_TOKCLASS_NONE ) ) { mbEmbedded = true; OSL_ENSURE( nFmlaSize == 5, "XclImpPictureObj::ReadPictFmla - unexpected formula size" ); rStrm.Ignore( nFmlaSize - 1 ); // token ID already read if( nFmlaSize & 1 ) rStrm.Ignore( 1 ); // padding byte // a class name may follow inside the picture link if( rStrm.GetRecPos() + 2 <= nLinkEnd ) { sal_uInt16 nLen; rStrm >> nLen; if( nLen > 0 ) maClassName = (GetBiff() == EXC_BIFF8) ? rStrm.ReadUniString( nLen ) : rStrm.ReadRawByteString( nLen ); } } // else: ignore other formulas, e.g. pictures linked to cell ranges } } // seek behind picture link data rStrm.Seek( nLinkEnd ); // read additional data for embedded OLE objects following the picture link if( IsOcxControl() ) { // #i26521# form controls to be ignored if( maClassName.EqualsAscii( "Forms.HTML:Hidden.1" ) ) { SetProcessSdrObj( false ); return; } if( rStrm.GetRecLeft() <= 8 ) return; // position and size of control data in 'Ctls' stream mnCtlsStrmPos = static_cast< sal_Size >( rStrm.ReaduInt32() ); mnCtlsStrmSize = static_cast< sal_Size >( rStrm.ReaduInt32() ); if( rStrm.GetRecLeft() <= 8 ) return; // additional string (16-bit characters), e.g. for progress bar control sal_uInt32 nAddStrSize; rStrm >> nAddStrSize; OSL_ENSURE( rStrm.GetRecLeft() >= nAddStrSize + 4, "XclImpPictureObj::ReadPictFmla - missing data" ); if( rStrm.GetRecLeft() >= nAddStrSize + 4 ) { rStrm.Ignore( nAddStrSize ); // cell link and source range ReadCellLinkFormula( rStrm, true ); ReadSourceRangeFormula( rStrm, true ); } } else if( mbEmbedded && (rStrm.GetRecLeft() >= 4) ) { rStrm >> mnStorageId; } } // DFF stream conversion ====================================================== void XclImpSolverContainer::InsertSdrObjectInfo( SdrObject& rSdrObj, sal_uInt32 nDffShapeId, sal_uInt32 nDffFlags ) { if( nDffShapeId > 0 ) { maSdrInfoMap[ nDffShapeId ].Set( &rSdrObj, nDffFlags ); maSdrObjMap[ &rSdrObj ] = nDffShapeId; } } void XclImpSolverContainer::RemoveSdrObjectInfo( SdrObject& rSdrObj ) { // remove info of passed object from the maps XclImpSdrObjMap::iterator aIt = maSdrObjMap.find( &rSdrObj ); if( aIt != maSdrObjMap.end() ) { maSdrInfoMap.erase( aIt->second ); maSdrObjMap.erase( aIt ); } // remove info of all child objects of a group object if( SdrObjGroup* pGroupObj = dynamic_cast< SdrObjGroup* >( &rSdrObj ) ) { if( SdrObjList* pSubList = pGroupObj->GetSubList() ) { // iterate flat over the list because this function already works recursively SdrObjListIter aObjIt( *pSubList, IM_FLAT ); for( SdrObject* pChildObj = aObjIt.Next(); pChildObj; pChildObj = aObjIt.Next() ) RemoveSdrObjectInfo( *pChildObj ); } } } void XclImpSolverContainer::UpdateConnectorRules() { for ( size_t i = 0, n = aCList.size(); i < n; ++i ) { SvxMSDffConnectorRule* pRule = aCList[ i ]; UpdateConnection( pRule->nShapeA, pRule->pAObj, &pRule->nSpFlagsA ); UpdateConnection( pRule->nShapeB, pRule->pBObj, &pRule->nSpFlagsB ); UpdateConnection( pRule->nShapeC, pRule->pCObj ); } } void XclImpSolverContainer::RemoveConnectorRules() { // base class from SVX uses plain untyped tools/List for ( size_t i = 0, n = aCList.size(); i < n; ++i ) { delete aCList[ i ]; } aCList.clear(); maSdrInfoMap.clear(); maSdrObjMap.clear(); } void XclImpSolverContainer::UpdateConnection( sal_uInt32 nDffShapeId, SdrObject*& rpSdrObj, sal_uInt32* pnDffFlags ) { XclImpSdrInfoMap::const_iterator aIt = maSdrInfoMap.find( nDffShapeId ); if( aIt != maSdrInfoMap.end() ) { rpSdrObj = aIt->second.mpSdrObj; if( pnDffFlags ) *pnDffFlags = aIt->second.mnDffFlags; } } // ---------------------------------------------------------------------------- XclImpSimpleDffConverter::XclImpSimpleDffConverter( const XclImpRoot& rRoot, SvStream& rDffStrm ) : SvxMSDffManager( rDffStrm, rRoot.GetBasePath(), 0, 0, rRoot.GetDoc().GetDrawLayer(), 1440, COL_DEFAULT, 24, 0 ), XclImpRoot( rRoot ) { SetSvxMSDffSettings( SVXMSDFF_SETTINGS_CROP_BITMAPS | SVXMSDFF_SETTINGS_IMPORT_EXCEL ); } XclImpSimpleDffConverter::~XclImpSimpleDffConverter() { } bool XclImpSimpleDffConverter::GetColorFromPalette( sal_uInt16 nIndex, Color& rColor ) const { ColorData nColor = GetPalette().GetColorData( static_cast< sal_uInt16 >( nIndex ) ); if( nColor == COL_AUTO ) return 0; rColor.SetColor( nColor ); return 1; } // ---------------------------------------------------------------------------- Reference< XComponentContext > lcl_getUnoCtx() { comphelper::ComponentContext aCtx( ::comphelper::getProcessServiceFactory() ); return aCtx.getUNOContext(); } XclImpDffConverter::XclImpDffConvData::XclImpDffConvData( XclImpDrawing& rDrawing, SdrModel& rSdrModel, SdrPage& rSdrPage ) : mrDrawing( rDrawing ), mrSdrModel( rSdrModel ), mrSdrPage( rSdrPage ), mnLastCtrlIndex( -1 ), mbHasCtrlForm( false ) { } // ---------------------------------------------------------------------------- XclImpDffConverter::XclImpDffConverter( const XclImpRoot& rRoot, SvStream& rDffStrm ) : XclImpSimpleDffConverter( rRoot, rDffStrm ), oox::ole::MSConvertOCXControls( rRoot.GetDocShell()->GetModel() ), maStdFormName( CREATE_OUSTRING( "Standard" ) ), mnOleImpFlags( 0 ) { const SvtFilterOptions& rFilterOpt = SvtFilterOptions::Get(); if( rFilterOpt.IsMathType2Math() ) mnOleImpFlags |= OLE_MATHTYPE_2_STARMATH; if( rFilterOpt.IsWinWord2Writer() ) mnOleImpFlags |= OLE_WINWORD_2_STARWRITER; if( rFilterOpt.IsPowerPoint2Impress() ) mnOleImpFlags |= OLE_POWERPOINT_2_STARIMPRESS; // try to open the 'Ctls' storage stream containing OCX control properties mxCtlsStrm = OpenStream( EXC_STREAM_CTLS ); // default text margin (convert EMU to drawing layer units) mnDefTextMargin = EXC_OBJ_TEXT_MARGIN; ScaleEmu( mnDefTextMargin ); } XclImpDffConverter::~XclImpDffConverter() { } String XclImpObjectManager::GetOleNameOverride( SCTAB nTab, sal_uInt16 nObjId ) { rtl::OUString sOleName; String sCodeName = GetExtDocOptions().GetCodeName( nTab ); if ( mxOleCtrlNameOverride->hasByName( sCodeName ) ) { Reference< XIndexContainer > xIdToOleName; mxOleCtrlNameOverride->getByName( sCodeName ) >>= xIdToOleName; xIdToOleName->getByIndex( nObjId ) >>= sOleName; } OSL_TRACE("XclImpObjectManager::GetOleNameOverride tab %d, ( module %s ) object id ( %d ) is %s", nTab, rtl::OUStringToOString( sCodeName, RTL_TEXTENCODING_UTF8 ).getStr(), nObjId, rtl::OUStringToOString( sOleName, RTL_TEXTENCODING_UTF8 ).getStr() ); return sOleName; } void XclImpDffConverter::StartProgressBar( sal_Size nProgressSize ) { mxProgress.reset( new ScfProgressBar( GetDocShell(), STR_PROGRESS_CALCULATING ) ); mxProgress->AddSegment( nProgressSize ); mxProgress->Activate(); } void XclImpDffConverter::Progress( sal_Size nDelta ) { OSL_ENSURE( mxProgress, "XclImpDffConverter::Progress - invalid call, no progress bar" ); mxProgress->Progress( nDelta ); } void XclImpDffConverter::InitializeDrawing( XclImpDrawing& rDrawing, SdrModel& rSdrModel, SdrPage& rSdrPage ) { XclImpDffConvDataRef xConvData( new XclImpDffConvData( rDrawing, rSdrModel, rSdrPage ) ); maDataStack.push_back( xConvData ); SetModel( &xConvData->mrSdrModel, 1440 ); } void XclImpDffConverter::ProcessObject( SdrObjList& rObjList, const XclImpDrawObjBase& rDrawObj ) { if( rDrawObj.IsProcessSdrObj() ) { if( const XclObjAnchor* pAnchor = rDrawObj.GetAnchor() ) { Rectangle aAnchorRect = GetConvData().mrDrawing.CalcAnchorRect( *pAnchor, false ); if( rDrawObj.IsValidSize( aAnchorRect ) ) { // CreateSdrObject() recursively creates embedded child objects SdrObjectPtr xSdrObj( rDrawObj.CreateSdrObject( *this, aAnchorRect, false ) ); if( xSdrObj.is() ) rDrawObj.PreProcessSdrObject( *this, *xSdrObj ); // call InsertSdrObject() also, if SdrObject is missing InsertSdrObject( rObjList, rDrawObj, xSdrObj.release() ); } } } } void XclImpDffConverter::ProcessDrawing( const XclImpDrawObjVector& rDrawObjs ) { SdrPage& rSdrPage = GetConvData().mrSdrPage; for( XclImpDrawObjVector::const_iterator aIt = rDrawObjs.begin(), aEnd = rDrawObjs.end(); aIt != aEnd; ++aIt ) ProcessObject( rSdrPage, **aIt ); } void XclImpDffConverter::ProcessDrawing( SvStream& rDffStrm ) { rDffStrm.Seek( STREAM_SEEK_TO_END ); if( rDffStrm.Tell() > 0 ) { rDffStrm.Seek( STREAM_SEEK_TO_BEGIN ); DffRecordHeader aHeader; rDffStrm >> aHeader; OSL_ENSURE( aHeader.nRecType == DFF_msofbtDgContainer, "XclImpDffConverter::ProcessDrawing - unexpected record" ); if( aHeader.nRecType == DFF_msofbtDgContainer ) ProcessDgContainer( rDffStrm, aHeader ); } } void XclImpDffConverter::FinalizeDrawing() { OSL_ENSURE( !maDataStack.empty(), "XclImpDffConverter::FinalizeDrawing - no drawing manager on stack" ); maDataStack.pop_back(); // restore previous model at core DFF converter if( !maDataStack.empty() ) SetModel( &maDataStack.back()->mrSdrModel, 1440 ); } SdrObject* XclImpDffConverter::CreateSdrObject( const XclImpTbxObjBase& rTbxObj, const Rectangle& rAnchorRect ) { SdrObjectPtr xSdrObj; OUString aServiceName = rTbxObj.GetServiceName(); if( SupportsOleObjects() && !aServiceName.isEmpty() ) try { // create the form control from scratch Reference< XFormComponent > xFormComp( ScfApiHelper::CreateInstance( GetDocShell(), aServiceName ), UNO_QUERY_THROW ); // set controls form, needed in virtual function InsertControl() InitControlForm(); // try to insert the control into the form ::com::sun::star::awt::Size aDummySize; Reference< XShape > xShape; XclImpDffConvData& rConvData = GetConvData(); if( rConvData.mxCtrlForm.is() && InsertControl( xFormComp, aDummySize, &xShape, sal_True ) ) { xSdrObj.reset( rTbxObj.CreateSdrObjectFromShape( xShape, rAnchorRect ) ); // try to attach a macro to the control ScriptEventDescriptor aDescriptor; if( (rConvData.mnLastCtrlIndex >= 0) && rTbxObj.FillMacroDescriptor( aDescriptor ) ) { Reference< XEventAttacherManager > xEventMgr( rConvData.mxCtrlForm, UNO_QUERY_THROW ); xEventMgr->registerScriptEvent( rConvData.mnLastCtrlIndex, aDescriptor ); } } } catch( const Exception& ) { } return xSdrObj.release(); } SdrObject* XclImpDffConverter::CreateSdrObject( const XclImpPictureObj& rPicObj, const Rectangle& rAnchorRect ) { SdrObjectPtr xSdrObj; if( SupportsOleObjects() ) { if( rPicObj.IsOcxControl() ) { if( mxCtlsStrm.Is() ) try { /* set controls form, needed in virtual function InsertControl() called from ReadOCXExcelKludgeStream() */ InitControlForm(); // read from mxCtlsStrm into xShape, insert the control model into the form Reference< XShape > xShape; if( GetConvData().mxCtrlForm.is() ) { Reference< XFormComponent > xFComp; com::sun::star::awt::Size aSz; // not used in import ReadOCXCtlsStream( mxCtlsStrm, xFComp, rPicObj.GetCtlsStreamPos(), rPicObj.GetCtlsStreamSize() ); // recreate the method formally known as // ReadOCXExcelKludgeStream( ) if ( xFComp.is() ) { ScfPropertySet aPropSet( xFComp ); aPropSet.SetStringProperty( CREATE_OUSTRING( "Name" ), rPicObj.GetObjName() ); InsertControl( xFComp, aSz,&xShape,true); xSdrObj.reset( rPicObj.CreateSdrObjectFromShape( xShape, rAnchorRect ) ); } } } catch( const Exception& ) { } } else { SfxObjectShell* pDocShell = GetDocShell(); SotStorageRef xSrcStrg = GetRootStorage(); String aStrgName = rPicObj.GetOleStorageName(); if( pDocShell && xSrcStrg.Is() && (aStrgName.Len() > 0) ) { // first try to resolve graphic from DFF storage Graphic aGraphic; Rectangle aVisArea; if( !GetBLIP( GetPropertyValue( DFF_Prop_pib ), aGraphic, &aVisArea ) ) { // if not found, use graphic from object (imported from IMGDATA record) aGraphic = rPicObj.GetGraphic(); aVisArea = rPicObj.GetVisArea(); } if( aGraphic.GetType() != GRAPHIC_NONE ) { ErrCode nError = ERRCODE_NONE; namespace cssea = ::com::sun::star::embed::Aspects; sal_Int64 nAspects = rPicObj.IsSymbol() ? cssea::MSOLE_ICON : cssea::MSOLE_CONTENT; xSdrObj.reset( CreateSdrOLEFromStorage( aStrgName, xSrcStrg, pDocShell->GetStorage(), aGraphic, rAnchorRect, aVisArea, 0, nError, mnOleImpFlags, nAspects ) ); } } } } return xSdrObj.release(); } bool XclImpDffConverter::SupportsOleObjects() const { return GetConvData().mrDrawing.SupportsOleObjects(); } // virtual functions ---------------------------------------------------------- void XclImpDffConverter::ProcessClientAnchor2( SvStream& rDffStrm, DffRecordHeader& rHeader, void* /*pClientData*/, DffObjData& rObjData ) { // find the OBJ record data related to the processed shape XclImpDffConvData& rConvData = GetConvData(); if( XclImpDrawObjBase* pDrawObj = rConvData.mrDrawing.FindDrawObj( rObjData.rSpHd ).get() ) { OSL_ENSURE( rHeader.nRecType == DFF_msofbtClientAnchor, "XclImpDffConverter::ProcessClientAnchor2 - no client anchor record" ); XclObjAnchor aAnchor; rHeader.SeekToContent( rDffStrm ); rDffStrm.SeekRel( 2 ); // flags rDffStrm >> aAnchor; // anchor format equal to BIFF5 OBJ records pDrawObj->SetAnchor( aAnchor ); rObjData.aChildAnchor = rConvData.mrDrawing.CalcAnchorRect( aAnchor, true ); rObjData.bChildAnchor = sal_True; } } SdrObject* XclImpDffConverter::ProcessObj( SvStream& rDffStrm, DffObjData& rDffObjData, void* pClientData, Rectangle& /*rTextRect*/, SdrObject* pOldSdrObj ) { XclImpDffConvData& rConvData = GetConvData(); /* pOldSdrObj passes a generated SdrObject. This function owns this object and can modify it. The function has either to return it back to caller or to delete it by itself. */ SdrObjectPtr xSdrObj( pOldSdrObj ); // find the OBJ record data related to the processed shape XclImpDrawObjRef xDrawObj = rConvData.mrDrawing.FindDrawObj( rDffObjData.rSpHd ); const Rectangle& rAnchorRect = rDffObjData.aChildAnchor; // Do not process the global page group shape (flag SP_FPATRIARCH) bool bGlobalPageGroup = ::get_flag< sal_uInt32 >( rDffObjData.nSpFlags, SP_FPATRIARCH ); if( !xDrawObj || !xDrawObj->IsProcessSdrObj() || bGlobalPageGroup ) return 0; // simply return, xSdrObj will be destroyed /* Pass pointer to top-level object back to caller. If the processed object is embedded in a group, the pointer is already set to the top-level parent object. */ XclImpDrawObjBase** ppTopLevelObj = reinterpret_cast< XclImpDrawObjBase** >( pClientData ); bool bIsTopLevel = !ppTopLevelObj || !*ppTopLevelObj; if( ppTopLevelObj && bIsTopLevel ) *ppTopLevelObj = xDrawObj.get(); // connectors don't have to be area objects if( dynamic_cast< SdrEdgeObj* >( xSdrObj.get() ) ) xDrawObj->SetAreaObj( false ); /* Check for valid size for all objects. Needed to ignore lots of invisible phantom objects from deleted rows or columns (for performance reasons). #i30816# Include objects embedded in groups. #i58780# Ignore group shapes, size is not initialized. */ bool bEmbeddedGroup = !bIsTopLevel && dynamic_cast< SdrObjGroup* >( xSdrObj.get() ); if( !bEmbeddedGroup && !xDrawObj->IsValidSize( rAnchorRect ) ) return 0; // simply return, xSdrObj will be destroyed // set shape information from DFF stream String aObjName = GetPropertyString( DFF_Prop_wzName, rDffStrm ); String aHyperlink = ReadHlinkProperty( rDffStrm ); bool bVisible = !GetPropertyBool( DFF_Prop_fHidden ); bool bAutoMargin = GetPropertyBool( DFF_Prop_AutoTextMargin ); xDrawObj->SetDffData( rDffObjData, aObjName, aHyperlink, bVisible, bAutoMargin ); /* Connect textbox data (string, alignment, text orientation) to object. don't ask for a text-ID, DFF export doesn't set one. */ if( XclImpTextObj* pTextObj = dynamic_cast< XclImpTextObj* >( xDrawObj.get() ) ) if( const XclImpObjTextData* pTextData = rConvData.mrDrawing.FindTextData( rDffObjData.rSpHd ) ) pTextObj->SetTextData( *pTextData ); // copy line and fill formatting of TBX form controls from DFF properties if( XclImpTbxObjBase* pTbxObj = dynamic_cast< XclImpTbxObjBase* >( xDrawObj.get() ) ) pTbxObj->SetDffProperties( *this ); // try to create a custom SdrObject that overwrites the passed object SdrObjectPtr xNewSdrObj( xDrawObj->CreateSdrObject( *this, rAnchorRect, true ) ); if( xNewSdrObj.is() ) xSdrObj.reset( xNewSdrObj.release() ); // process the SdrObject if( xSdrObj.is() ) { // filled without color -> set system window color if( GetPropertyBool( DFF_Prop_fFilled ) && !IsProperty( DFF_Prop_fillColor ) ) xSdrObj->SetMergedItem( XFillColorItem( EMPTY_STRING, GetPalette().GetColor( EXC_COLOR_WINDOWBACK ) ) ); // additional processing on the SdrObject xDrawObj->PreProcessSdrObject( *this, *xSdrObj ); /* If the SdrObject will not be inserted into the draw page, delete it here. Happens e.g. for notes: The PreProcessSdrObject() call above has inserted the note into the document, and the SdrObject is not needed anymore. */ if( !xDrawObj->IsInsertSdrObj() ) xSdrObj.reset(); } if( xSdrObj.is() ) { /* Store the relation between shape ID and SdrObject for connectors. Must be done here (and not in InsertSdrObject() function), otherwise all SdrObjects embedded in groups would be lost. */ rConvData.maSolverCont.InsertSdrObjectInfo( *xSdrObj, xDrawObj->GetDffShapeId(), xDrawObj->GetDffFlags() ); /* If the drawing object is embedded in a group object, call PostProcessSdrObject() here. For top-level objects this will be done automatically in InsertSdrObject() but grouped shapes are inserted into their groups somewhere in the SvxMSDffManager base class without chance of notification. Unfortunately, now this is called before the object is really inserted into its group object, but that should not have any effect for grouped objects. */ if( !bIsTopLevel ) xDrawObj->PostProcessSdrObject( *this, *xSdrObj ); } return xSdrObj.release(); } sal_uLong XclImpDffConverter::Calc_nBLIPPos( sal_uLong /*nOrgVal*/, sal_uLong nStreamPos ) const { return nStreamPos + 4; } sal_Bool XclImpDffConverter::InsertControl( const Reference< XFormComponent >& rxFormComp, const ::com::sun::star::awt::Size& /*rSize*/, Reference< XShape >* pxShape, sal_Bool /*bFloatingCtrl*/ ) { if( GetDocShell() ) try { XclImpDffConvData& rConvData = GetConvData(); Reference< XIndexContainer > xFormIC( rConvData.mxCtrlForm, UNO_QUERY_THROW ); Reference< XControlModel > xCtrlModel( rxFormComp, UNO_QUERY_THROW ); // create the control shape Reference< XShape > xShape( ScfApiHelper::CreateInstance( GetDocShell(), CREATE_OUSTRING( "com.sun.star.drawing.ControlShape" ) ), UNO_QUERY_THROW ); Reference< XControlShape > xCtrlShape( xShape, UNO_QUERY_THROW ); // insert the new control into the form sal_Int32 nNewIndex = xFormIC->getCount(); xFormIC->insertByIndex( nNewIndex, Any( rxFormComp ) ); // on success: store new index of the control for later use (macro events) rConvData.mnLastCtrlIndex = nNewIndex; // set control model at control shape and pass back shape to caller xCtrlShape->setControl( xCtrlModel ); if( pxShape ) *pxShape = xShape; return sal_True; } catch( const Exception& ) { OSL_FAIL( "XclImpDffConverter::InsertControl - cannot create form control" ); } return false; } // private -------------------------------------------------------------------- XclImpDffConverter::XclImpDffConvData& XclImpDffConverter::GetConvData() { OSL_ENSURE( !maDataStack.empty(), "XclImpDffConverter::GetConvData - no drawing manager on stack" ); return *maDataStack.back(); } const XclImpDffConverter::XclImpDffConvData& XclImpDffConverter::GetConvData() const { OSL_ENSURE( !maDataStack.empty(), "XclImpDffConverter::GetConvData - no drawing manager on stack" ); return *maDataStack.back(); } String XclImpDffConverter::ReadHlinkProperty( SvStream& rDffStrm ) const { /* Reads hyperlink data from a complex DFF property. Contents of this property are equal to the HLINK record, import of this record is implemented in class XclImpHyperlink. This function has to create an instance of the XclImpStream class to be able to reuse the functionality of XclImpHyperlink. */ String aString; sal_uInt32 nBufferSize = GetPropertyValue( DFF_Prop_pihlShape ); if( (0 < nBufferSize) && (nBufferSize <= 0xFFFF) && SeekToContent( DFF_Prop_pihlShape, rDffStrm ) ) { // create a faked BIFF record that can be read by XclImpStream class SvMemoryStream aMemStream; aMemStream << sal_uInt16( 0 ) << static_cast< sal_uInt16 >( nBufferSize ); // copy from DFF stream to memory stream ::std::vector< sal_uInt8 > aBuffer( nBufferSize ); sal_uInt8* pnData = &aBuffer.front(); if( rDffStrm.Read( pnData, nBufferSize ) == nBufferSize ) { aMemStream.Write( pnData, nBufferSize ); // create BIFF import stream to be able to use XclImpHyperlink class XclImpStream aXclStrm( aMemStream, GetRoot() ); if( aXclStrm.StartNextRecord() ) aString = XclImpHyperlink::ReadEmbeddedData( aXclStrm ); } } return aString; } void XclImpDffConverter::ProcessDgContainer( SvStream& rDffStrm, const DffRecordHeader& rDgHeader ) { sal_Size nEndPos = rDgHeader.GetRecEndFilePos(); while( rDffStrm.Tell() < nEndPos ) { DffRecordHeader aHeader; rDffStrm >> aHeader; switch( aHeader.nRecType ) { case DFF_msofbtSolverContainer: ProcessSolverContainer( rDffStrm, aHeader ); break; case DFF_msofbtSpgrContainer: ProcessShGrContainer( rDffStrm, aHeader ); break; default: aHeader.SeekToEndOfRecord( rDffStrm ); } } // seek to end of drawing page container rDgHeader.SeekToEndOfRecord( rDffStrm ); // #i12638# #i37900# connector rules XclImpSolverContainer& rSolverCont = GetConvData().maSolverCont; rSolverCont.UpdateConnectorRules(); SolveSolver( rSolverCont ); rSolverCont.RemoveConnectorRules(); } void XclImpDffConverter::ProcessShGrContainer( SvStream& rDffStrm, const DffRecordHeader& rShGrHeader ) { sal_Size nEndPos = rShGrHeader.GetRecEndFilePos(); while( rDffStrm.Tell() < nEndPos ) { DffRecordHeader aHeader; rDffStrm >> aHeader; switch( aHeader.nRecType ) { case DFF_msofbtSpgrContainer: case DFF_msofbtSpContainer: ProcessShContainer( rDffStrm, aHeader ); break; default: aHeader.SeekToEndOfRecord( rDffStrm ); } } // seek to end of shape group container rShGrHeader.SeekToEndOfRecord( rDffStrm ); } void XclImpDffConverter::ProcessSolverContainer( SvStream& rDffStrm, const DffRecordHeader& rSolverHeader ) { // solver container wants to read the solver container header again rSolverHeader.SeekToBegOfRecord( rDffStrm ); // read the entire solver container rDffStrm >> GetConvData().maSolverCont; // seek to end of solver container rSolverHeader.SeekToEndOfRecord( rDffStrm ); } void XclImpDffConverter::ProcessShContainer( SvStream& rDffStrm, const DffRecordHeader& rShHeader ) { rShHeader.SeekToBegOfRecord( rDffStrm ); Rectangle aDummy; const XclImpDrawObjBase* pDrawObj = 0; /* The call to ImportObj() creates and returns a new SdrObject for the processed shape. We take ownership of the returned object here. If the shape is a group object, all embedded objects are created recursively, and the returned group object contains them all. ImportObj() calls the virtual functions ProcessClientAnchor2() and ProcessObj() and writes the pointer to the related draw object data (OBJ record) into pDrawObj. */ SdrObjectPtr xSdrObj( ImportObj( rDffStrm, &pDrawObj, aDummy, aDummy, 0, 0 ) ); if( pDrawObj && xSdrObj.is() ) InsertSdrObject( GetConvData().mrSdrPage, *pDrawObj, xSdrObj.release() ); rShHeader.SeekToEndOfRecord( rDffStrm ); } void XclImpDffConverter::InsertSdrObject( SdrObjList& rObjList, const XclImpDrawObjBase& rDrawObj, SdrObject* pSdrObj ) { XclImpDffConvData& rConvData = GetConvData(); /* Take ownership of the passed object. If insertion fails (e.g. rDrawObj states to skip insertion), the object is automatically deleted. */ SdrObjectPtr xSdrObj( pSdrObj ); if( xSdrObj.is() && rDrawObj.IsInsertSdrObj() ) { rObjList.NbcInsertObject( xSdrObj.release() ); // callback to drawing manager for e.g. tracking of used sheet area rConvData.mrDrawing.OnObjectInserted( rDrawObj ); // callback to drawing object for post processing (use pSdrObj, xSdrObj already released) rDrawObj.PostProcessSdrObject( *this, *pSdrObj ); } /* SdrObject still here? Insertion failed, remove data from shape ID map. The SdrObject will be destructed then. */ if( xSdrObj.is() ) rConvData.maSolverCont.RemoveSdrObjectInfo( *xSdrObj ); } void XclImpDffConverter::InitControlForm() { XclImpDffConvData& rConvData = GetConvData(); if( rConvData.mbHasCtrlForm ) return; rConvData.mbHasCtrlForm = true; if( SupportsOleObjects() ) try { Reference< XFormsSupplier > xFormsSupplier( rConvData.mrSdrPage.getUnoPage(), UNO_QUERY_THROW ); Reference< XNameContainer > xFormsNC( xFormsSupplier->getForms(), UNO_SET_THROW ); // find or create the Standard form used to insert the imported controls if( xFormsNC->hasByName( maStdFormName ) ) { xFormsNC->getByName( maStdFormName ) >>= rConvData.mxCtrlForm; } else if( SfxObjectShell* pDocShell = GetDocShell() ) { rConvData.mxCtrlForm.set( ScfApiHelper::CreateInstance( pDocShell, CREATE_OUSTRING( "com.sun.star.form.component.Form" ) ), UNO_QUERY_THROW ); xFormsNC->insertByName( maStdFormName, Any( rConvData.mxCtrlForm ) ); } } catch( const Exception& ) { } } // Drawing manager ============================================================ XclImpDrawing::XclImpDrawing( const XclImpRoot& rRoot, bool bOleObjects ) : XclImpRoot( rRoot ), mbOleObjs( bOleObjects ) { } XclImpDrawing::~XclImpDrawing() { } Graphic XclImpDrawing::ReadImgData( const XclImpRoot& rRoot, XclImpStream& rStrm ) { Graphic aGraphic; sal_uInt16 nFormat, nEnv; sal_uInt32 nDataSize; rStrm >> nFormat >> nEnv >> nDataSize; if( nDataSize <= rStrm.GetRecLeft() ) { switch( nFormat ) { case EXC_IMGDATA_WMF: ReadWmf( aGraphic, rRoot, rStrm ); break; case EXC_IMGDATA_BMP: ReadBmp( aGraphic, rRoot, rStrm ); break; default: OSL_FAIL( "XclImpDrawing::ReadImgData - unknown image format" ); } } return aGraphic; } void XclImpDrawing::ReadObj( XclImpStream& rStrm ) { XclImpDrawObjRef xDrawObj; /* #i61786# In BIFF8 streams, OBJ records may occur without MSODRAWING records. In this case, the OBJ records are in BIFF5 format. Do a sanity check here that there is no DFF data loaded before. */ OSL_ENSURE( maDffStrm.Tell() == 0, "XclImpDrawing::ReadObj - unexpected DFF stream data, OBJ will be ignored" ); if( maDffStrm.Tell() == 0 ) switch( GetBiff() ) { case EXC_BIFF3: xDrawObj = XclImpDrawObjBase::ReadObj3( GetRoot(), rStrm ); break; case EXC_BIFF4: xDrawObj = XclImpDrawObjBase::ReadObj4( GetRoot(), rStrm ); break; case EXC_BIFF5: case EXC_BIFF8: xDrawObj = XclImpDrawObjBase::ReadObj5( GetRoot(), rStrm ); break; default: DBG_ERROR_BIFF(); } if( xDrawObj ) { // insert into maRawObjs or into the last open group object maRawObjs.InsertGrouped( xDrawObj ); // to be able to find objects by ID maObjMapId[ xDrawObj->GetObjId() ] = xDrawObj; } } void XclImpDrawing::ReadMsoDrawing( XclImpStream& rStrm ) { OSL_ENSURE_BIFF( GetBiff() == EXC_BIFF8 ); // disable internal CONTINUE handling rStrm.ResetRecord( false ); // read leading MSODRAWING record ReadDffRecord( rStrm ); // read following drawing records, but do not start following unrelated record bool bLoop = true; while( bLoop ) switch( rStrm.GetNextRecId() ) { case EXC_ID_MSODRAWING: case EXC_ID_MSODRAWINGSEL: case EXC_ID_CONT: rStrm.StartNextRecord(); ReadDffRecord( rStrm ); break; case EXC_ID_OBJ: rStrm.StartNextRecord(); ReadObj8( rStrm ); break; case EXC_ID_TXO: rStrm.StartNextRecord(); ReadTxo( rStrm ); break; default: bLoop = false; } // re-enable internal CONTINUE handling rStrm.ResetRecord( true ); } XclImpDrawObjRef XclImpDrawing::FindDrawObj( const DffRecordHeader& rHeader ) const { /* maObjMap stores objects by position of the client data (OBJ record) in the DFF stream, which is always behind shape start position of the passed header. The function upper_bound() finds the first element in the map whose key is greater than the start position of the header. Its end position is used to test whether the found object is really related to the shape. */ XclImpDrawObjRef xDrawObj; XclImpObjMap::const_iterator aIt = maObjMap.upper_bound( rHeader.GetRecBegFilePos() ); if( (aIt != maObjMap.end()) && (aIt->first <= rHeader.GetRecEndFilePos()) ) xDrawObj = aIt->second; return xDrawObj; } XclImpDrawObjRef XclImpDrawing::FindDrawObj( sal_uInt16 nObjId ) const { XclImpDrawObjRef xDrawObj; XclImpObjMapById::const_iterator aIt = maObjMapId.find( nObjId ); if( aIt != maObjMapId.end() ) xDrawObj = aIt->second; return xDrawObj; } const XclImpObjTextData* XclImpDrawing::FindTextData( const DffRecordHeader& rHeader ) const { /* maTextMap stores textbox data by position of the client data (TXO record) in the DFF stream, which is always behind shape start position of the passed header. The function upper_bound() finds the first element in the map whose key is greater than the start position of the header. Its end position is used to test whether the found object is really related to the shape. */ XclImpObjTextMap::const_iterator aIt = maTextMap.upper_bound( rHeader.GetRecBegFilePos() ); if( (aIt != maTextMap.end()) && (aIt->first <= rHeader.GetRecEndFilePos()) ) return aIt->second.get(); return 0; } void XclImpDrawing::SetSkipObj( sal_uInt16 nObjId ) { maSkipObjs.push_back( nObjId ); } sal_Size XclImpDrawing::GetProgressSize() const { sal_Size nProgressSize = maRawObjs.GetProgressSize(); for( XclImpObjMap::const_iterator aIt = maObjMap.begin(), aEnd = maObjMap.end(); aIt != aEnd; ++aIt ) nProgressSize += aIt->second->GetProgressSize(); return nProgressSize; } void XclImpDrawing::ImplConvertObjects( XclImpDffConverter& rDffConv, SdrModel& rSdrModel, SdrPage& rSdrPage ) { //rhbz#636521, disable undo during conversion. faster, smaller and stops //temp objects being inserted into the undo list bool bOrigUndoStatus = rSdrModel.IsUndoEnabled(); rSdrModel.EnableUndo(false); // register this drawing manager at the passed (global) DFF manager rDffConv.InitializeDrawing( *this, rSdrModel, rSdrPage ); // process list of objects to be skipped for( ScfUInt16Vec::const_iterator aIt = maSkipObjs.begin(), aEnd = maSkipObjs.end(); aIt != aEnd; ++aIt ) if( XclImpDrawObjBase* pDrawObj = FindDrawObj( *aIt ).get() ) pDrawObj->SetProcessSdrObj( false ); // process drawing objects without DFF data rDffConv.ProcessDrawing( maRawObjs ); // process all objects in the DFF stream rDffConv.ProcessDrawing( maDffStrm ); // unregister this drawing manager at the passed (global) DFF manager rDffConv.FinalizeDrawing(); rSdrModel.EnableUndo(bOrigUndoStatus); } // protected ------------------------------------------------------------------ void XclImpDrawing::AppendRawObject( const XclImpDrawObjRef& rxDrawObj ) { OSL_ENSURE( rxDrawObj, "XclImpDrawing::AppendRawObject - unexpected empty reference" ); maRawObjs.push_back( rxDrawObj ); } // private -------------------------------------------------------------------- void XclImpDrawing::ReadWmf( Graphic& rGraphic, const XclImpRoot&, XclImpStream& rStrm ) // static helper { // extract graphic data from IMGDATA and following CONTINUE records rStrm.Ignore( 8 ); SvMemoryStream aMemStrm; rStrm.CopyToStream( aMemStrm, rStrm.GetRecLeft() ); aMemStrm.Seek( STREAM_SEEK_TO_BEGIN ); // import the graphic from memory stream GDIMetaFile aGDIMetaFile; if( ::ReadWindowMetafile( aMemStrm, aGDIMetaFile, 0 ) ) rGraphic = aGDIMetaFile; } void XclImpDrawing::ReadBmp( Graphic& rGraphic, const XclImpRoot& rRoot, XclImpStream& rStrm ) // static helper { // extract graphic data from IMGDATA and following CONTINUE records SvMemoryStream aMemStrm; /* Excel 3 and 4 seem to write broken BMP data. Usually they write a DIBCOREHEADER (12 bytes) containing width, height, planes = 1, and pixel depth = 32 bit. After that, 3 unused bytes are added before the actual pixel data. This does even confuse Excel 5 and later, which cannot read the image data correctly. */ if( rRoot.GetBiff() <= EXC_BIFF4 ) { rStrm.PushPosition(); sal_uInt32 nHdrSize; sal_uInt16 nWidth, nHeight, nPlanes, nDepth; rStrm >> nHdrSize >> nWidth >> nHeight >> nPlanes >> nDepth; if( (nHdrSize == 12) && (nPlanes == 1) && (nDepth == 32) ) { rStrm.Ignore( 3 ); aMemStrm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); aMemStrm << nHdrSize << nWidth << nHeight << nPlanes << nDepth; rStrm.CopyToStream( aMemStrm, rStrm.GetRecLeft() ); } rStrm.PopPosition(); } // no special handling above -> just copy the remaining record data if( aMemStrm.Tell() == 0 ) rStrm.CopyToStream( aMemStrm, rStrm.GetRecLeft() ); // import the graphic from memory stream aMemStrm.Seek( STREAM_SEEK_TO_BEGIN ); Bitmap aBitmap; if( aBitmap.Read( aMemStrm, false ) ) // read DIB without file header rGraphic = aBitmap; } void XclImpDrawing::ReadDffRecord( XclImpStream& rStrm ) { maDffStrm.Seek( STREAM_SEEK_TO_END ); rStrm.CopyRecordToStream( maDffStrm ); } void XclImpDrawing::ReadObj8( XclImpStream& rStrm ) { XclImpDrawObjRef xDrawObj = XclImpDrawObjBase::ReadObj8( GetRoot(), rStrm ); // store the new object in the internal containers maObjMap[ maDffStrm.Tell() ] = xDrawObj; maObjMapId[ xDrawObj->GetObjId() ] = xDrawObj; } void XclImpDrawing::ReadTxo( XclImpStream& rStrm ) { XclImpObjTextRef xTextData( new XclImpObjTextData ); maTextMap[ maDffStrm.Tell() ] = xTextData; // 1) read the TXO record xTextData->maData.ReadTxo8( rStrm ); // 2) first CONTINUE with string xTextData->mxString.reset(); bool bValid = true; if( xTextData->maData.mnTextLen > 0 ) { bValid = (rStrm.GetNextRecId() == EXC_ID_CONT) && rStrm.StartNextRecord(); OSL_ENSURE( bValid, "XclImpDrawing::ReadTxo - missing CONTINUE record" ); if( bValid ) xTextData->mxString.reset( new XclImpString( rStrm.ReadUniString( xTextData->maData.mnTextLen ) ) ); } // 3) second CONTINUE with formatting runs if( xTextData->maData.mnFormatSize > 0 ) { bValid = (rStrm.GetNextRecId() == EXC_ID_CONT) && rStrm.StartNextRecord(); OSL_ENSURE( bValid, "XclImpDrawing::ReadTxo - missing CONTINUE record" ); if( bValid ) xTextData->ReadFormats( rStrm ); } } // ---------------------------------------------------------------------------- XclImpSheetDrawing::XclImpSheetDrawing( const XclImpRoot& rRoot, SCTAB nScTab ) : XclImpDrawing( rRoot, true ), maScUsedArea( ScAddress::INITIALIZE_INVALID ) { maScUsedArea.aStart.SetTab( nScTab ); maScUsedArea.aEnd.SetTab( nScTab ); } void XclImpSheetDrawing::ReadNote( XclImpStream& rStrm ) { switch( GetBiff() ) { case EXC_BIFF2: case EXC_BIFF3: case EXC_BIFF4: case EXC_BIFF5: ReadNote3( rStrm ); break; case EXC_BIFF8: ReadNote8( rStrm ); break; default: DBG_ERROR_BIFF(); } } void XclImpSheetDrawing::ReadTabChart( XclImpStream& rStrm ) { OSL_ENSURE_BIFF( GetBiff() >= EXC_BIFF5 ); boost::shared_ptr< XclImpChartObj > xChartObj( new XclImpChartObj( GetRoot(), true ) ); xChartObj->ReadChartSubStream( rStrm ); // insert the chart as raw object without connected DFF data AppendRawObject( xChartObj ); } void XclImpSheetDrawing::ConvertObjects( XclImpDffConverter& rDffConv ) { if( SdrModel* pSdrModel = GetDoc().GetDrawLayer() ) if( SdrPage* pSdrPage = GetSdrPage( maScUsedArea.aStart.Tab() ) ) ImplConvertObjects( rDffConv, *pSdrModel, *pSdrPage ); } Rectangle XclImpSheetDrawing::CalcAnchorRect( const XclObjAnchor& rAnchor, bool /*bDffAnchor*/ ) const { return rAnchor.GetRect( GetRoot(), maScUsedArea.aStart.Tab(), MAP_100TH_MM ); } void XclImpSheetDrawing::OnObjectInserted( const XclImpDrawObjBase& rDrawObj ) { ScRange aScObjArea = rDrawObj.GetUsedArea( maScUsedArea.aStart.Tab() ); if( aScObjArea.IsValid() ) maScUsedArea.ExtendTo( aScObjArea ); } // private -------------------------------------------------------------------- void XclImpSheetDrawing::ReadNote3( XclImpStream& rStrm ) { XclAddress aXclPos; sal_uInt16 nTotalLen; rStrm >> aXclPos >> nTotalLen; ScAddress aScNotePos( ScAddress::UNINITIALIZED ); if( GetAddressConverter().ConvertAddress( aScNotePos, aXclPos, maScUsedArea.aStart.Tab(), true ) ) { sal_uInt16 nPartLen = ::std::min( nTotalLen, static_cast< sal_uInt16 >( rStrm.GetRecLeft() ) ); String aNoteText = rStrm.ReadRawByteString( nPartLen ); nTotalLen = nTotalLen - nPartLen; while( (nTotalLen > 0) && (rStrm.GetNextRecId() == EXC_ID_NOTE) && rStrm.StartNextRecord() ) { rStrm >> aXclPos >> nPartLen; OSL_ENSURE( aXclPos.mnRow == 0xFFFF, "XclImpObjectManager::ReadNote3 - missing continuation NOTE record" ); if( aXclPos.mnRow == 0xFFFF ) { OSL_ENSURE( nPartLen <= nTotalLen, "XclImpObjectManager::ReadNote3 - string too long" ); aNoteText.Append( rStrm.ReadRawByteString( nPartLen ) ); nTotalLen = nTotalLen - ::std::min( nTotalLen, nPartLen ); } else { // seems to be a new note, record already started -> load the note rStrm.Seek( EXC_REC_SEEK_TO_BEGIN ); ReadNote( rStrm ); nTotalLen = 0; } } ScNoteUtil::CreateNoteFromString( GetDoc(), aScNotePos, aNoteText, false, false ); } } void XclImpSheetDrawing::ReadNote8( XclImpStream& rStrm ) { XclAddress aXclPos; sal_uInt16 nFlags, nObjId; rStrm >> aXclPos >> nFlags >> nObjId; ScAddress aScNotePos( ScAddress::UNINITIALIZED ); if( GetAddressConverter().ConvertAddress( aScNotePos, aXclPos, maScUsedArea.aStart.Tab(), true ) ) if( nObjId != EXC_OBJ_INVALID_ID ) if( XclImpNoteObj* pNoteObj = dynamic_cast< XclImpNoteObj* >( FindDrawObj( nObjId ).get() ) ) pNoteObj->SetNoteData( aScNotePos, nFlags ); } // The object manager ========================================================= XclImpObjectManager::XclImpObjectManager( const XclImpRoot& rRoot ) : XclImpRoot( rRoot ) { maDefObjNames[ EXC_OBJTYPE_GROUP ] = CREATE_STRING( "Group" ); maDefObjNames[ EXC_OBJTYPE_LINE ] = ScGlobal::GetRscString( STR_SHAPE_LINE ); maDefObjNames[ EXC_OBJTYPE_RECTANGLE ] = ScGlobal::GetRscString( STR_SHAPE_RECTANGLE ); maDefObjNames[ EXC_OBJTYPE_OVAL ] = ScGlobal::GetRscString( STR_SHAPE_OVAL ); maDefObjNames[ EXC_OBJTYPE_ARC ] = CREATE_STRING( "Arc" ); maDefObjNames[ EXC_OBJTYPE_CHART ] = CREATE_STRING( "Chart" ); maDefObjNames[ EXC_OBJTYPE_TEXT ] = CREATE_STRING( "Text" ); maDefObjNames[ EXC_OBJTYPE_BUTTON ] = ScGlobal::GetRscString( STR_FORM_BUTTON ); maDefObjNames[ EXC_OBJTYPE_PICTURE ] = CREATE_STRING( "Picture" ); maDefObjNames[ EXC_OBJTYPE_POLYGON ] = CREATE_STRING( "Freeform" ); maDefObjNames[ EXC_OBJTYPE_CHECKBOX ] = ScGlobal::GetRscString( STR_FORM_CHECKBOX ); maDefObjNames[ EXC_OBJTYPE_OPTIONBUTTON ] = ScGlobal::GetRscString( STR_FORM_OPTIONBUTTON ); maDefObjNames[ EXC_OBJTYPE_EDIT ] = CREATE_STRING( "Edit Box" ); maDefObjNames[ EXC_OBJTYPE_LABEL ] = ScGlobal::GetRscString( STR_FORM_LABEL ); maDefObjNames[ EXC_OBJTYPE_DIALOG ] = CREATE_STRING( "Dialog Frame" ); maDefObjNames[ EXC_OBJTYPE_SPIN ] = ScGlobal::GetRscString( STR_FORM_SPINNER ); maDefObjNames[ EXC_OBJTYPE_SCROLLBAR ] = ScGlobal::GetRscString( STR_FORM_SCROLLBAR ); maDefObjNames[ EXC_OBJTYPE_LISTBOX ] = ScGlobal::GetRscString( STR_FORM_LISTBOX ); maDefObjNames[ EXC_OBJTYPE_GROUPBOX ] = ScGlobal::GetRscString( STR_FORM_GROUPBOX ); maDefObjNames[ EXC_OBJTYPE_DROPDOWN ] = ScGlobal::GetRscString( STR_FORM_DROPDOWN ); maDefObjNames[ EXC_OBJTYPE_NOTE ] = CREATE_STRING( "Comment" ); maDefObjNames[ EXC_OBJTYPE_DRAWING ] = ScGlobal::GetRscString( STR_SHAPE_AUTOSHAPE ); } XclImpObjectManager::~XclImpObjectManager() { } void XclImpObjectManager::ReadMsoDrawingGroup( XclImpStream& rStrm ) { OSL_ENSURE_BIFF( GetBiff() == EXC_BIFF8 ); // Excel continues this record with MSODRAWINGGROUP and CONTINUE records, hmm. rStrm.ResetRecord( true, EXC_ID_MSODRAWINGGROUP ); maDggStrm.Seek( STREAM_SEEK_TO_END ); rStrm.CopyRecordToStream( maDggStrm ); } XclImpSheetDrawing& XclImpObjectManager::GetSheetDrawing( SCTAB nScTab ) { XclImpSheetDrawingRef& rxDrawing = maSheetDrawings[ nScTab ]; if( !rxDrawing ) rxDrawing.reset( new XclImpSheetDrawing( GetRoot(), nScTab ) ); return *rxDrawing; } void XclImpObjectManager::ConvertObjects() { RTL_LOGFILE_CONTEXT_AUTHOR( aLog, "sc", "dr104026", "XclImpObjectManager::ConvertObjects" ); // do nothing if the document does not contain a drawing layer if( !GetDoc().GetDrawLayer() ) return; // get total progress bar size for all sheet drawing managers sal_Size nProgressSize = 0; for( XclImpSheetDrawingMap::iterator aIt = maSheetDrawings.begin(), aEnd = maSheetDrawings.end(); aIt != aEnd; ++aIt ) nProgressSize += aIt->second->GetProgressSize(); // nothing to do if progress bar is zero (no objects present) if( nProgressSize == 0 ) return; XclImpDffConverter aDffConv( GetRoot(), maDggStrm ); aDffConv.StartProgressBar( nProgressSize ); for( XclImpSheetDrawingMap::iterator aIt = maSheetDrawings.begin(), aEnd = maSheetDrawings.end(); aIt != aEnd; ++aIt ) aIt->second->ConvertObjects( aDffConv ); // #i112436# don't call ScChartListenerCollection::SetDirty here, // instead use InterpretDirtyCells in ScDocument::CalcAfterLoad. } OUString XclImpObjectManager::GetDefaultObjName( const XclImpDrawObjBase& rDrawObj ) const { rtl::OUStringBuffer aDefName; DefObjNameMap::const_iterator aIt = maDefObjNames.find( rDrawObj.GetObjType() ); if( aIt != maDefObjNames.end() ) aDefName.append(aIt->second); return aDefName.append(' ').append(static_cast(rDrawObj.GetObjId())).makeStringAndClear(); } ScRange XclImpObjectManager::GetUsedArea( SCTAB nScTab ) const { XclImpSheetDrawingMap::const_iterator aIt = maSheetDrawings.find( nScTab ); if( aIt != maSheetDrawings.end() ) return aIt->second->GetUsedArea(); return ScRange( ScAddress::INITIALIZE_INVALID ); } // DFF property set helper ==================================================== XclImpDffPropSet::XclImpDffPropSet( const XclImpRoot& rRoot ) : XclImpRoot( rRoot ), maDffConv( rRoot, maDummyStrm ) { } void XclImpDffPropSet::Read( XclImpStream& rStrm ) { sal_uInt32 nPropSetSize; rStrm.PushPosition(); rStrm.Ignore( 4 ); rStrm >> nPropSetSize; rStrm.PopPosition(); mxMemStrm.reset( new SvMemoryStream ); rStrm.CopyToStream( *mxMemStrm, 8 + nPropSetSize ); mxMemStrm->Seek( STREAM_SEEK_TO_BEGIN ); maDffConv.ReadPropSet( *mxMemStrm, 0 ); } sal_uInt32 XclImpDffPropSet::GetPropertyValue( sal_uInt16 nPropId, sal_uInt32 nDefault ) const { return maDffConv.GetPropertyValue( nPropId, nDefault ); } void XclImpDffPropSet::FillToItemSet( SfxItemSet& rItemSet ) const { if( mxMemStrm.get() ) maDffConv.ApplyAttributes( *mxMemStrm, rItemSet ); } XclImpStream& operator>>( XclImpStream& rStrm, XclImpDffPropSet& rPropSet ) { rPropSet.Read( rStrm ); return rStrm; } // ============================================================================ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */