summaryrefslogtreecommitdiff
path: root/oox/source/ole
diff options
context:
space:
mode:
Diffstat (limited to 'oox/source/ole')
-rwxr-xr-x[-rw-r--r--]oox/source/ole/axbinaryreader.cxx100
-rw-r--r--oox/source/ole/axcontrol.cxx1122
-rw-r--r--oox/source/ole/axcontrolfragment.cxx35
-rw-r--r--oox/source/ole/axcontrolhelper.cxx175
-rw-r--r--oox/source/ole/makefile.mk8
-rw-r--r--oox/source/ole/olehelper.cxx112
-rwxr-xr-xoox/source/ole/olestorage.cxx423
-rwxr-xr-xoox/source/ole/vbacontrol.cxx811
-rwxr-xr-xoox/source/ole/vbahelper.cxx248
-rwxr-xr-xoox/source/ole/vbamodule.cxx241
-rwxr-xr-xoox/source/ole/vbaproject.cxx519
11 files changed, 3247 insertions, 547 deletions
diff --git a/oox/source/ole/axbinaryreader.cxx b/oox/source/ole/axbinaryreader.cxx
index f49776ef70e5..cb7e292b8cf4 100644..100755
--- a/oox/source/ole/axbinaryreader.cxx
+++ b/oox/source/ole/axbinaryreader.cxx
@@ -89,13 +89,80 @@ void AxAlignedInputStream::align( size_t nSize )
// ============================================================================
+AxFontData::AxFontData() :
+ mnFontEffects( 0 ),
+ mnFontHeight( 160 ),
+ mnFontCharSet( WINDOWS_CHARSET_DEFAULT ),
+ mnHorAlign( AX_FONTDATA_LEFT )
+{
+}
+
+sal_Int16 AxFontData::getHeightPoints() const
+{
+ /* MSO uses weird font sizes:
+ 1pt->30, 2pt->45, 3pt->60, 4pt->75, 5pt->105, 6pt->120, 7pt->135,
+ 8pt->165, 9pt->180, 10pt->195, 11pt->225, ... */
+ return getLimitedValue< sal_Int16, sal_Int32 >( (mnFontHeight + 10) / 20, 1, SAL_MAX_INT16 );
+}
+
+void AxFontData::setHeightPoints( sal_Int16 nPoints )
+{
+ mnFontHeight = getLimitedValue< sal_Int32, sal_Int32 >( ((nPoints * 4 + 1) / 3) * 15, 30, 4294967 );
+}
+
+bool AxFontData::importBinaryModel( BinaryInputStream& rInStrm )
+{
+ AxBinaryPropertyReader aReader( rInStrm );
+ aReader.readStringProperty( maFontName );
+ aReader.readIntProperty< sal_uInt32 >( mnFontEffects );
+ aReader.readIntProperty< sal_Int32 >( mnFontHeight );
+ aReader.skipIntProperty< sal_Int32 >(); // font offset
+ aReader.readIntProperty< sal_uInt8 >( mnFontCharSet );
+ aReader.skipIntProperty< sal_uInt8 >(); // font pitch/family
+ aReader.readIntProperty< sal_uInt8 >( mnHorAlign );
+ aReader.skipIntProperty< sal_uInt16 >(); // font weight
+ return aReader.finalizeImport();
+}
+
+bool AxFontData::importStdFont( BinaryInputStream& rInStrm )
+{
+ StdFontInfo aFontInfo;
+ if( OleHelper::importStdFont( aFontInfo, rInStrm, false ) )
+ {
+ maFontName = aFontInfo.maName;
+ mnFontEffects = 0;
+ setFlag( mnFontEffects, AX_FONTDATA_BOLD, aFontInfo.mnWeight >= OLE_STDFONT_BOLD );
+ setFlag( mnFontEffects, AX_FONTDATA_ITALIC, getFlag( aFontInfo.mnFlags, OLE_STDFONT_ITALIC ) );
+ setFlag( mnFontEffects, AX_FONTDATA_UNDERLINE, getFlag( aFontInfo.mnFlags, OLE_STDFONT_UNDERLINE ) );
+ setFlag( mnFontEffects, AX_FONTDATA_STRIKEOUT, getFlag( aFontInfo.mnFlags,OLE_STDFONT_STRIKE ) );
+ // StdFont stores font height in 1/10,000 of points
+ setHeightPoints( getLimitedValue< sal_Int16, sal_Int32 >( aFontInfo.mnHeight / 10000, 0, SAL_MAX_INT16 ) );
+ mnFontCharSet = aFontInfo.mnCharSet;
+ mnHorAlign = AX_FONTDATA_LEFT;
+ return true;
+ }
+ return false;
+}
+
+bool AxFontData::importGuidAndFont( BinaryInputStream& rInStrm )
+{
+ OUString aGuid = OleHelper::importGuid( rInStrm );
+ if( aGuid.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "{AFC20920-DA4E-11CE-B943-00AA006887B4}" ) ) )
+ return importBinaryModel( rInStrm );
+ if( aGuid.equalsAscii( OLE_GUID_STDFONT ) )
+ return importStdFont( rInStrm );
+ return false;
+}
+
+// ============================================================================
+
AxBinaryPropertyReader::ComplexProperty::~ComplexProperty()
{
}
bool AxBinaryPropertyReader::PairProperty::readProperty( AxAlignedInputStream& rInStrm )
{
- rInStrm >> mrnValue1 >> mrnValue2;
+ rInStrm >> mrPairData.first >> mrPairData.second;
return true;
}
@@ -116,6 +183,17 @@ bool AxBinaryPropertyReader::StringProperty::readProperty( AxAlignedInputStream&
return bValidChars;
}
+bool AxBinaryPropertyReader::GuidProperty::readProperty( AxAlignedInputStream& rInStrm )
+{
+ mrGuid = OleHelper::importGuid( rInStrm );
+ return true;
+}
+
+bool AxBinaryPropertyReader::FontProperty::readProperty( AxAlignedInputStream& rInStrm )
+{
+ return mrFontData.importGuidAndFont( rInStrm );
+}
+
bool AxBinaryPropertyReader::PictureProperty::readProperty( AxAlignedInputStream& rInStrm )
{
return OleHelper::importStdPic( mrPicData, rInStrm, true );
@@ -145,10 +223,10 @@ void AxBinaryPropertyReader::readBoolProperty( bool& orbValue, bool bReverse )
orbValue = startNextProperty() != bReverse;
}
-void AxBinaryPropertyReader::readPairProperty( sal_Int32& ornValue1, sal_Int32& ornValue2 )
+void AxBinaryPropertyReader::readPairProperty( AxPairData& orPairData )
{
if( startNextProperty() )
- maLargeProps.push_back( ComplexPropVector::value_type( new PairProperty( ornValue1, ornValue2 ) ) );
+ maLargeProps.push_back( ComplexPropVector::value_type( new PairProperty( orPairData ) ) );
}
void AxBinaryPropertyReader::readStringProperty( OUString& orValue )
@@ -160,6 +238,22 @@ void AxBinaryPropertyReader::readStringProperty( OUString& orValue )
}
}
+void AxBinaryPropertyReader::readGuidProperty( ::rtl::OUString& orGuid )
+{
+ if( startNextProperty() )
+ maLargeProps.push_back( ComplexPropVector::value_type( new GuidProperty( orGuid ) ) );
+}
+
+void AxBinaryPropertyReader::readFontProperty( AxFontData& orFontData )
+{
+ if( startNextProperty() )
+ {
+ sal_Int16 nData = maInStrm.readAligned< sal_Int16 >();
+ if( ensureValid( nData == -1 ) )
+ maStreamProps.push_back( ComplexPropVector::value_type( new FontProperty( orFontData ) ) );
+ }
+}
+
void AxBinaryPropertyReader::readPictureProperty( StreamDataSequence& orPicData )
{
if( startNextProperty() )
diff --git a/oox/source/ole/axcontrol.cxx b/oox/source/ole/axcontrol.cxx
index 96baaab4bb36..95d5c7dc67b7 100644
--- a/oox/source/ole/axcontrol.cxx
+++ b/oox/source/ole/axcontrol.cxx
@@ -27,20 +27,24 @@
#include "oox/ole/axcontrol.hxx"
#include <rtl/tencinfo.h>
-#include <com/sun/star/lang/XMultiServiceFactory.hpp>
-#include <com/sun/star/container/XIndexContainer.hpp>
#include <com/sun/star/awt/FontSlant.hpp>
#include <com/sun/star/awt/FontStrikeout.hpp>
#include <com/sun/star/awt/FontUnderline.hpp>
#include <com/sun/star/awt/FontWeight.hpp>
#include <com/sun/star/awt/ImagePosition.hpp>
#include <com/sun/star/awt/ImageScaleMode.hpp>
+#include <com/sun/star/awt/Point.hpp>
#include <com/sun/star/awt/ScrollBarOrientation.hpp>
+#include <com/sun/star/awt/Size.hpp>
#include <com/sun/star/awt/TextAlign.hpp>
#include <com/sun/star/awt/VisualEffect.hpp>
#include <com/sun/star/awt/XControlModel.hpp>
-#include <com/sun/star/style/VerticalAlignment.hpp>
+#include <com/sun/star/container/XIndexContainer.hpp>
+#include <com/sun/star/form/XForm.hpp>
#include <com/sun/star/form/XFormComponent.hpp>
+#include <com/sun/star/form/XFormsSupplier.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/style/VerticalAlignment.hpp>
#include "properties.hxx"
#include "tokens.hxx"
#include "oox/helper/attributelist.hxx"
@@ -48,20 +52,23 @@
#include "oox/helper/graphichelper.hxx"
#include "oox/helper/propertymap.hxx"
#include "oox/helper/propertyset.hxx"
-#include "oox/core/filterbase.hxx"
-#include "oox/ole/axbinaryreader.hxx"
-#include "oox/ole/axcontrolhelper.hxx"
-#include "oox/ole/olehelper.hxx"
using ::rtl::OUString;
+using ::com::sun::star::awt::Point;
+using ::com::sun::star::awt::Size;
+using ::com::sun::star::awt::XControlModel;
+using ::com::sun::star::container::XIndexContainer;
+using ::com::sun::star::container::XNameContainer;
+using ::com::sun::star::drawing::XDrawPage;
+using ::com::sun::star::form::XForm;
+using ::com::sun::star::form::XFormComponent;
+using ::com::sun::star::lang::XMultiServiceFactory;
using ::com::sun::star::uno::Any;
using ::com::sun::star::uno::Exception;
using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::uno::UNO_QUERY_THROW;
-using ::com::sun::star::container::XIndexContainer;
-using ::com::sun::star::awt::XControlModel;
-using ::com::sun::star::form::XFormComponent;
-using ::oox::core::FilterBase;
+using ::com::sun::star::uno::UNO_SET_THROW;
namespace oox {
namespace ole {
@@ -70,6 +77,29 @@ namespace ole {
namespace {
+const sal_uInt32 COMCTL_ID_SIZE = 0x12344321;
+
+const sal_uInt32 COMCTL_ID_COMMONDATA = 0xABCDEF01;
+const sal_uInt32 COMCTL_COMMON_FLATBORDER = 0x00000001;
+const sal_uInt32 COMCTL_COMMON_ENABLED = 0x00000002;
+const sal_uInt32 COMCTL_COMMON_3DBORDER = 0x00000004;
+const sal_uInt32 COMCTL_COMMON_OLEDROPMAN = 0x00002000;
+
+const sal_uInt32 COMCTL_ID_COMPLEXDATA = 0xBDECDE1F;
+const sal_uInt32 COMCTL_COMPLEX_FONT = 0x00000001;
+const sal_uInt32 COMCTL_COMPLEX_MOUSEICON = 0x00000002;
+
+const sal_uInt32 COMCTL_ID_SCROLLBAR_60 = 0x99470A83;
+const sal_uInt32 COMCTL_SCROLLBAR_HOR = 0x00000010;
+const sal_Int32 COMCTL_SCROLLBAR_3D = 0;
+const sal_Int32 COMCTL_SCROLLBAR_FLAT = 1;
+const sal_Int32 COMCTL_SCROLLBAR_TRACK3D = 2;
+
+const sal_uInt32 COMCTL_ID_PROGRESSBAR_50 = 0xE6E17E84;
+const sal_uInt32 COMCTL_ID_PROGRESSBAR_60 = 0x97AB8A01;
+
+// ----------------------------------------------------------------------------
+
const sal_uInt32 AX_FLAGS_ENABLED = 0x00000002;
const sal_uInt32 AX_FLAGS_LOCKED = 0x00000004;
const sal_uInt32 AX_FLAGS_OPAQUE = 0x00000008;
@@ -99,26 +129,6 @@ const sal_uInt32 AX_MORPHDATA_DEFFLAGS = 0x2C80081B;
const sal_uInt32 AX_SPINBUTTON_DEFFLAGS = 0x0000001B;
const sal_uInt32 AX_SCROLLBAR_DEFFLAGS = 0x0000001B;
-const sal_uInt32 AX_FONT_BOLD = 0x00000001;
-const sal_uInt32 AX_FONT_ITALIC = 0x00000002;
-const sal_uInt32 AX_FONT_UNDERLINE = 0x00000004;
-const sal_uInt32 AX_FONT_STRIKEOUT = 0x00000008;
-const sal_uInt32 AX_FONT_DISABLED = 0x00002000;
-const sal_uInt32 AX_FONT_AUTOCOLOR = 0x40000000;
-
-const sal_Int32 AX_FONTALIGN_LEFT = 1;
-const sal_Int32 AX_FONTALIGN_RIGHT = 2;
-const sal_Int32 AX_FONTALIGN_CENTER = 3;
-
-const sal_Int32 AX_BORDERSTYLE_NONE = 0;
-const sal_Int32 AX_BORDERSTYLE_SINGLE = 1;
-
-const sal_Int32 AX_SPECIALEFFECT_FLAT = 0;
-const sal_Int32 AX_SPECIALEFFECT_RAISED = 1;
-const sal_Int32 AX_SPECIALEFFECT_SUNKEN = 2;
-const sal_Int32 AX_SPECIALEFFECT_ETCHED = 3;
-const sal_Int32 AX_SPECIALEFFECT_BUMPED = 6;
-
const sal_uInt16 AX_POS_TOPLEFT = 0;
const sal_uInt16 AX_POS_TOP = 1;
const sal_uInt16 AX_POS_TOPRIGHT = 2;
@@ -129,31 +139,21 @@ const sal_uInt16 AX_POS_BOTTOMLEFT = 6;
const sal_uInt16 AX_POS_BOTTOM = 7;
const sal_uInt16 AX_POS_BOTTOMRIGHT = 8;
-#define AX_PICPOS( label, image ) ((AX_POS_##label << 16) | AX_POS_##image)
-const sal_uInt32 AX_PICPOS_LEFTTOP = AX_PICPOS( TOPRIGHT, TOPLEFT );
-const sal_uInt32 AX_PICPOS_LEFTCENTER = AX_PICPOS( RIGHT, LEFT );
-const sal_uInt32 AX_PICPOS_LEFTBOTTOM = AX_PICPOS( BOTTOMRIGHT, BOTTOMLEFT );
-const sal_uInt32 AX_PICPOS_RIGHTTOP = AX_PICPOS( TOPLEFT, TOPRIGHT );
-const sal_uInt32 AX_PICPOS_RIGHTCENTER = AX_PICPOS( LEFT, RIGHT );
-const sal_uInt32 AX_PICPOS_RIGHTBOTTOM = AX_PICPOS( BOTTOMLEFT, BOTTOMRIGHT );
-const sal_uInt32 AX_PICPOS_ABOVELEFT = AX_PICPOS( BOTTOMLEFT, TOPLEFT );
-const sal_uInt32 AX_PICPOS_ABOVECENTER = AX_PICPOS( BOTTOM, TOP );
-const sal_uInt32 AX_PICPOS_ABOVERIGHT = AX_PICPOS( BOTTOMRIGHT, TOPRIGHT );
-const sal_uInt32 AX_PICPOS_BELOWLEFT = AX_PICPOS( TOPLEFT, BOTTOMLEFT );
-const sal_uInt32 AX_PICPOS_BELOWCENTER = AX_PICPOS( TOP, BOTTOM );
-const sal_uInt32 AX_PICPOS_BELOWRIGHT = AX_PICPOS( TOPRIGHT, BOTTOMRIGHT );
-const sal_uInt32 AX_PICPOS_CENTER = AX_PICPOS( CENTER, CENTER );
-#undef AX_PICPOS
-
-const sal_Int32 AX_PICSIZE_CLIP = 0;
-const sal_Int32 AX_PICSIZE_STRETCH = 1;
-const sal_Int32 AX_PICSIZE_ZOOM = 3;
-
-const sal_Int32 AX_PICALIGN_TOPLEFT = 0;
-const sal_Int32 AX_PICALIGN_TOPRIGHT = 1;
-const sal_Int32 AX_PICALIGN_CENTER = 2;
-const sal_Int32 AX_PICALIGN_BOTTOMLEFT = 3;
-const sal_Int32 AX_PICALIGN_BOTTOMRIGHT = 4;
+#define AX_PICPOS_IMPL( label, image ) ((AX_POS_##label << 16) | AX_POS_##image)
+const sal_uInt32 AX_PICPOS_LEFTTOP = AX_PICPOS_IMPL( TOPRIGHT, TOPLEFT );
+const sal_uInt32 AX_PICPOS_LEFTCENTER = AX_PICPOS_IMPL( RIGHT, LEFT );
+const sal_uInt32 AX_PICPOS_LEFTBOTTOM = AX_PICPOS_IMPL( BOTTOMRIGHT, BOTTOMLEFT );
+const sal_uInt32 AX_PICPOS_RIGHTTOP = AX_PICPOS_IMPL( TOPLEFT, TOPRIGHT );
+const sal_uInt32 AX_PICPOS_RIGHTCENTER = AX_PICPOS_IMPL( LEFT, RIGHT );
+const sal_uInt32 AX_PICPOS_RIGHTBOTTOM = AX_PICPOS_IMPL( BOTTOMLEFT, BOTTOMRIGHT );
+const sal_uInt32 AX_PICPOS_ABOVELEFT = AX_PICPOS_IMPL( BOTTOMLEFT, TOPLEFT );
+const sal_uInt32 AX_PICPOS_ABOVECENTER = AX_PICPOS_IMPL( BOTTOM, TOP );
+const sal_uInt32 AX_PICPOS_ABOVERIGHT = AX_PICPOS_IMPL( BOTTOMRIGHT, TOPRIGHT );
+const sal_uInt32 AX_PICPOS_BELOWLEFT = AX_PICPOS_IMPL( TOPLEFT, BOTTOMLEFT );
+const sal_uInt32 AX_PICPOS_BELOWCENTER = AX_PICPOS_IMPL( TOP, BOTTOM );
+const sal_uInt32 AX_PICPOS_BELOWRIGHT = AX_PICPOS_IMPL( TOPRIGHT, BOTTOMRIGHT );
+const sal_uInt32 AX_PICPOS_CENTER = AX_PICPOS_IMPL( CENTER, CENTER );
+#undef AX_PICPOS_IMPL
const sal_Int32 AX_DISPLAYSTYLE_TEXT = 1;
const sal_Int32 AX_DISPLAYSTYLE_LISTBOX = 2;
@@ -186,6 +186,25 @@ const sal_Int32 AX_ORIENTATION_HORIZONTAL = 1;
const sal_Int32 AX_PROPTHUMB_ON = -1;
const sal_Int32 AX_PROPTHUMB_OFF = 0;
+const sal_uInt32 AX_CONTAINER_ENABLED = 0x00000004;
+const sal_uInt32 AX_CONTAINER_HASDESIGNEXT = 0x00004000;
+const sal_uInt32 AX_CONTAINER_NOCLASSTABLE = 0x00008000;
+
+const sal_uInt32 AX_CONTAINER_DEFFLAGS = 0x00000004;
+
+const sal_Int32 AX_CONTAINER_DEFWIDTH = 4000;
+const sal_Int32 AX_CONTAINER_DEFHEIGHT = 3000;
+
+const sal_Int32 AX_CONTAINER_CYCLEALL = 0;
+const sal_Int32 AX_CONTAINER_CYCLECURRENT = 2;
+
+const sal_Int32 AX_CONTAINER_SCR_NONE = 0x00;
+const sal_Int32 AX_CONTAINER_SCR_HOR = 0x01;
+const sal_Int32 AX_CONTAINER_SCR_VER = 0x02;
+const sal_Int32 AX_CONTAINER_SCR_KEEP_HOR = 0x04;
+const sal_Int32 AX_CONTAINER_SCR_KEEP_VER = 0x08;
+const sal_Int32 AX_CONTAINER_SCR_SHOW_LEFT = 0x10;
+
// ----------------------------------------------------------------------------
const sal_Int16 API_BORDER_NONE = 0;
@@ -196,37 +215,82 @@ const sal_Int16 API_STATE_UNCHECKED = 0;
const sal_Int16 API_STATE_CHECKED = 1;
const sal_Int16 API_STATE_DONTKNOW = 2;
-// ----------------------------------------------------------------------------
+} // namespace
+
+// ============================================================================
-/** Specifies how a form control supports transparent background. */
-enum ApiTransparencyMode
+ControlConverter::ControlConverter( const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr ) :
+ mrGraphicHelper( rGraphicHelper ),
+ mbDefaultColorBgr( bDefaultColorBgr )
{
- API_TRANSPARENCY_NOTSUPPORTED, /// Control does not support transparency.
- API_TRANSPARENCY_VOID, /// Transparency is enabled by missing fill color.
- API_TRANSPARENCY_PAINTTRANSPARENT /// Transparency is enabled by the 'PaintTransparent' property.
-};
+}
-// ----------------------------------------------------------------------------
+ControlConverter::~ControlConverter()
+{
+}
-/** Specifies how a form control supports the DefaultState property. */
-enum ApiDefaultStateMode
+// Generic conversion ---------------------------------------------------------
+
+void ControlConverter::convertSize( PropertyMap& rPropMap, const AxPairData& rSize ) const
{
- API_DEFAULTSTATE_BOOLEAN, /// Control does not support tri-state, state is given as boolean.
- API_DEFAULTSTATE_SHORT, /// Control does not support tri-state, state is given as short.
- API_DEFAULTSTATE_TRISTATE /// Control supports tri-state, state is given as short.
-};
+ // size is given in 1/100 mm, UNO needs AppFont units
+ Size aAppFontSize = mrGraphicHelper.convertHmmToAppFont( Size( rSize.first, rSize.second ) );
+ rPropMap.setProperty( PROP_Width, aAppFontSize.Width );
+ rPropMap.setProperty( PROP_Height, aAppFontSize.Height );
+}
-// ----------------------------------------------------------------------------
+void ControlConverter::convertPosition( PropertyMap& rPropMap, const AxPairData& rPos ) const
+{
+ // position is given in 1/100 mm, UNO needs AppFont units
+ Point aAppFontPos = mrGraphicHelper.convertHmmToAppFont( Point( rPos.first, rPos.second ) );
+ rPropMap.setProperty( PROP_PositionX, aAppFontPos.X );
+ rPropMap.setProperty( PROP_PositionY, aAppFontPos.Y );
+}
+
+void ControlConverter::convertColor( PropertyMap& rPropMap, sal_Int32 nPropId, sal_uInt32 nOleColor ) const
+{
+ rPropMap.setProperty( nPropId, OleHelper::decodeOleColor( mrGraphicHelper, nOleColor, mbDefaultColorBgr ) );
+}
+
+void ControlConverter::convertPicture( PropertyMap& rPropMap, const StreamDataSequence& rPicData ) const
+{
+ if( rPicData.hasElements() )
+ {
+ OUString aGraphicUrl = mrGraphicHelper.importGraphicObject( rPicData );
+ if( aGraphicUrl.getLength() > 0 )
+ rPropMap.setProperty( PROP_ImageURL, aGraphicUrl );
+ }
+}
+
+void ControlConverter::convertOrientation( PropertyMap& rPropMap, bool bHorizontal ) const
+{
+ namespace AwtScrollBarOrient = ::com::sun::star::awt::ScrollBarOrientation;
+ sal_Int32 nScrollOrient = bHorizontal ? AwtScrollBarOrient::HORIZONTAL : AwtScrollBarOrient::VERTICAL;
+ rPropMap.setProperty( PROP_Orientation, nScrollOrient );
+}
-/** Converts the AX background formatting to UNO properties. */
-void lclConvertBackground( AxControlHelper& rHelper, PropertyMap& rPropMap, sal_uInt32 nBackColor, sal_uInt32 nFlags, ApiTransparencyMode eTranspMode )
+void ControlConverter::convertScrollBar( PropertyMap& rPropMap,
+ sal_Int32 nMin, sal_Int32 nMax, sal_Int32 nPosition,
+ sal_Int32 nSmallChange, sal_Int32 nLargeChange, bool bAwtModel ) const
+{
+ rPropMap.setProperty( PROP_ScrollValueMin, ::std::min( nMin, nMax ) );
+ rPropMap.setProperty( PROP_ScrollValueMax, ::std::max( nMin, nMax ) );
+ rPropMap.setProperty( PROP_LineIncrement, nSmallChange );
+ rPropMap.setProperty( PROP_BlockIncrement, nLargeChange );
+ rPropMap.setProperty( bAwtModel ? PROP_ScrollValue : PROP_DefaultScrollValue, nPosition );
+}
+
+// ActiveX (Forms 2.0) specific conversion ------------------------------------
+
+void ControlConverter::convertAxBackground( PropertyMap& rPropMap,
+ sal_uInt32 nBackColor, sal_uInt32 nFlags, ApiTransparencyMode eTranspMode ) const
{
bool bOpaque = getFlag( nFlags, AX_FLAGS_OPAQUE );
switch( eTranspMode )
{
case API_TRANSPARENCY_NOTSUPPORTED:
// fake transparency by using system window background if needed
- rPropMap.setProperty( PROP_BackgroundColor, rHelper.convertColor( bOpaque ? nBackColor : AX_SYSCOLOR_WINDOWBACK ) );
+ convertColor( rPropMap, PROP_BackgroundColor, bOpaque ? nBackColor : AX_SYSCOLOR_WINDOWBACK );
break;
case API_TRANSPARENCY_PAINTTRANSPARENT:
rPropMap.setProperty( PROP_PaintTransparent, !bOpaque );
@@ -234,52 +298,31 @@ void lclConvertBackground( AxControlHelper& rHelper, PropertyMap& rPropMap, sal_
case API_TRANSPARENCY_VOID:
// keep transparency by leaving the (void) default property value
if( bOpaque )
- rPropMap.setProperty( PROP_BackgroundColor, rHelper.convertColor( nBackColor ) );
+ convertColor( rPropMap, PROP_BackgroundColor, nBackColor );
break;
}
}
-// ----------------------------------------------------------------------------
-
-/** Converts the AX border formatting to UNO properties. */
-void lclConvertBorder( AxControlHelper& rHelper, PropertyMap& rPropMap, sal_uInt32 nBorderColor, sal_Int32 nBorderStyle, sal_Int32 nSpecialEffect )
+void ControlConverter::convertAxBorder( PropertyMap& rPropMap,
+ sal_uInt32 nBorderColor, sal_Int32 nBorderStyle, sal_Int32 nSpecialEffect ) const
{
sal_Int16 nBorder = (nBorderStyle == AX_BORDERSTYLE_SINGLE) ? API_BORDER_FLAT :
((nSpecialEffect == AX_SPECIALEFFECT_FLAT) ? API_BORDER_NONE : API_BORDER_SUNKEN);
rPropMap.setProperty( PROP_Border, nBorder );
- rPropMap.setProperty( PROP_BorderColor, rHelper.convertColor( nBorderColor ) );
+ convertColor( rPropMap, PROP_BorderColor, nBorderColor );
}
-// ----------------------------------------------------------------------------
-
-/** Converts the AX special effect to UNO properties. */
-void lclConvertVisualEffect( AxControlHelper& /*rHelper*/, PropertyMap& rPropMap, sal_Int32 nSpecialEffect )
+void ControlConverter::convertAxVisualEffect( PropertyMap& rPropMap, sal_Int32 nSpecialEffect ) const
{
namespace AwtVisualEffect = ::com::sun::star::awt::VisualEffect;
sal_Int16 nVisualEffect = (nSpecialEffect == AX_SPECIALEFFECT_FLAT) ? AwtVisualEffect::FLAT : AwtVisualEffect::LOOK3D;
rPropMap.setProperty( PROP_VisualEffect, nVisualEffect );
}
-// ----------------------------------------------------------------------------
-
-/** Converts the passed picture stream to UNO properties. */
-void lclConvertPicture( AxControlHelper& rHelper, PropertyMap& rPropMap, const StreamDataSequence& rPicData )
-{
- if( rPicData.hasElements() )
- {
- OUString aGraphicUrl = rHelper.getFilter().getGraphicHelper().importGraphicObject( rPicData );
- if( aGraphicUrl.getLength() > 0 )
- rPropMap.setProperty( PROP_ImageURL, aGraphicUrl );
- }
-}
-
-// ----------------------------------------------------------------------------
-
-/** Converts the passed picture stream and position to UNO properties. */
-void lclConvertPicture( AxControlHelper& rHelper, PropertyMap& rPropMap, const StreamDataSequence& rPicData, sal_uInt32 nPicPos )
+void ControlConverter::convertAxPicture( PropertyMap& rPropMap, const StreamDataSequence& rPicData, sal_uInt32 nPicPos ) const
{
// the picture
- lclConvertPicture( rHelper, rPropMap, rPicData );
+ convertPicture( rPropMap, rPicData );
// picture position
namespace AwtImagePos = ::com::sun::star::awt::ImagePosition;
@@ -299,18 +342,16 @@ void lclConvertPicture( AxControlHelper& rHelper, PropertyMap& rPropMap, const S
case AX_PICPOS_BELOWCENTER: nImagePos = AwtImagePos::BelowCenter; break;
case AX_PICPOS_BELOWRIGHT: nImagePos = AwtImagePos::BelowRight; break;
case AX_PICPOS_CENTER: nImagePos = AwtImagePos::Centered; break;
- default: OSL_ENSURE( false, "lclConvertPicture - unknown picture position" );
+ default: OSL_ENSURE( false, "ControlConverter::convertAxPicture - unknown picture position" );
}
rPropMap.setProperty( PROP_ImagePosition, nImagePos );
}
-// ----------------------------------------------------------------------------
-
-/** Converts the passed picture stream and position to UNO properties. */
-void lclConvertPicture( AxControlHelper& rHelper, PropertyMap& rPropMap, const StreamDataSequence& rPicData, sal_Int32 nPicSizeMode, sal_Int32 /*nPicAlign*/, bool /*bPicTiling*/ )
+void ControlConverter::convertAxPicture( PropertyMap& rPropMap, const StreamDataSequence& rPicData,
+ sal_Int32 nPicSizeMode, sal_Int32 /*nPicAlign*/, bool /*bPicTiling*/ ) const
{
// the picture
- lclConvertPicture( rHelper, rPropMap, rPicData );
+ convertPicture( rPropMap, rPicData );
// picture scale mode
namespace AwtScaleMode = ::com::sun::star::awt::ImageScaleMode;
@@ -320,15 +361,13 @@ void lclConvertPicture( AxControlHelper& rHelper, PropertyMap& rPropMap, const S
case AX_PICSIZE_CLIP: nScaleMode = AwtScaleMode::None; break;
case AX_PICSIZE_STRETCH: nScaleMode = AwtScaleMode::Anisotropic; break;
case AX_PICSIZE_ZOOM: nScaleMode = AwtScaleMode::Isotropic; break;
- default: OSL_ENSURE( false, "lclConvertPicture - unknown picture size mode" );
+ default: OSL_ENSURE( false, "ControlConverter::convertAxPicture - unknown picture size mode" );
}
rPropMap.setProperty( PROP_ScaleMode, nScaleMode );
}
-// ----------------------------------------------------------------------------
-
-/** Converts the AX value for checked/unchecked/dontknow to UNO properties. */
-void lclConvertState( AxControlHelper& /*rHelper*/, PropertyMap& rPropMap, const OUString& rValue, sal_Int32 nMultiSelect, ApiDefaultStateMode eDefStateMode )
+void ControlConverter::convertAxState( PropertyMap& rPropMap,
+ const OUString& rValue, sal_Int32 nMultiSelect, ApiDefaultStateMode eDefStateMode, bool bAwtModel ) const
{
bool bBooleanState = eDefStateMode == API_DEFAULTSTATE_BOOLEAN;
bool bSupportsTriState = eDefStateMode == API_DEFAULTSTATE_TRISTATE;
@@ -341,44 +380,280 @@ void lclConvertState( AxControlHelper& /*rHelper*/, PropertyMap& rPropMap, const
case '1': nState = API_STATE_CHECKED; break;
// any other string (also empty) means 'dontknow'
}
+ sal_Int32 nPropId = bAwtModel ? PROP_State : PROP_DefaultState;
if( bBooleanState )
- rPropMap.setProperty( PROP_DefaultState, nState != API_STATE_UNCHECKED );
+ rPropMap.setProperty( nPropId, nState != API_STATE_UNCHECKED );
else
- rPropMap.setProperty( PROP_DefaultState, nState );
+ rPropMap.setProperty( nPropId, nState );
// tristate
if( bSupportsTriState )
rPropMap.setProperty( PROP_TriState, nMultiSelect == AX_SELCTION_MULTI );
}
-// ----------------------------------------------------------------------------
-
-/** Converts the AX control orientation to UNO properties. */
-void lclConvertOrientation( AxControlHelper& /*rHelper*/, PropertyMap& rPropMap, sal_Int32 nOrientation, sal_Int32 nWidth, sal_Int32 nHeight )
+void ControlConverter::convertAxOrientation( PropertyMap& rPropMap,
+ const AxPairData& rSize, sal_Int32 nOrientation ) const
{
- namespace AwtScrollBarOrient = ::com::sun::star::awt::ScrollBarOrientation;
- sal_Int32 nScrollOrient = AwtScrollBarOrient::HORIZONTAL;
+ bool bHorizontal = true;
switch( nOrientation )
{
- case AX_ORIENTATION_AUTO: if( nWidth <= nHeight) nScrollOrient = AwtScrollBarOrient::VERTICAL; break;
- case AX_ORIENTATION_VERTICAL: nScrollOrient = AwtScrollBarOrient::VERTICAL; break;
- case AX_ORIENTATION_HORIZONTAL: nScrollOrient = AwtScrollBarOrient::HORIZONTAL; break;
- default: OSL_ENSURE( false, "lclConvertOrientation - unknown orientation" );
+ case AX_ORIENTATION_AUTO: bHorizontal = rSize.first > rSize.second; break;
+ case AX_ORIENTATION_VERTICAL: bHorizontal = false; break;
+ case AX_ORIENTATION_HORIZONTAL: bHorizontal = true; break;
+ default: OSL_ENSURE( false, "ControlConverter::convertAxOrientation - unknown orientation" );
}
- rPropMap.setProperty( PROP_Orientation, nScrollOrient );
+ convertOrientation( rPropMap, bHorizontal );
}
-} // namespace
+// ============================================================================
+
+ControlModelBase::ControlModelBase() :
+ maSize( 0, 0 ),
+ mbAwtModel( false )
+{
+}
+
+ControlModelBase::~ControlModelBase()
+{
+}
+
+OUString ControlModelBase::getServiceName() const
+{
+ ApiControlType eCtrlType = getControlType();
+ if( mbAwtModel ) switch( eCtrlType )
+ {
+ case API_CONTROL_BUTTON: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlButtonModel" );
+ case API_CONTROL_FIXEDTEXT: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlFixedTextModel" );
+ case API_CONTROL_IMAGE: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlImageControlModel" );
+ case API_CONTROL_CHECKBOX: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlCheckBoxModel" );
+ case API_CONTROL_RADIOBUTTON: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlRadioButtonModel" );
+ case API_CONTROL_EDIT: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlEditModel" );
+ case API_CONTROL_LISTBOX: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlListBoxModel" );
+ case API_CONTROL_COMBOBOX: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlComboBoxModel" );
+ case API_CONTROL_SPINBUTTON: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlSpinButtonModel" );
+ case API_CONTROL_SCROLLBAR: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlScrollBarModel" );
+ case API_CONTROL_PROGRESSBAR: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlProgressBarModel" );
+ case API_CONTROL_GROUPBOX: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlGroupBoxModel" );
+ case API_CONTROL_DIALOG: return CREATE_OUSTRING( "com.sun.star.awt.UnoControlDialogModel" );
+ default: OSL_ENSURE( false, "ControlModelBase::getServiceName - no AWT model service supported" );
+ }
+ else switch( eCtrlType )
+ {
+ case API_CONTROL_BUTTON: return CREATE_OUSTRING( "com.sun.star.form.component.CommandButton" );
+ case API_CONTROL_FIXEDTEXT: return CREATE_OUSTRING( "com.sun.star.form.component.FixedText" );
+ case API_CONTROL_IMAGE: return CREATE_OUSTRING( "com.sun.star.form.component.DatabaseImageControl" );
+ case API_CONTROL_CHECKBOX: return CREATE_OUSTRING( "com.sun.star.form.component.CheckBox" );
+ case API_CONTROL_RADIOBUTTON: return CREATE_OUSTRING( "com.sun.star.form.component.RadioButton" );
+ case API_CONTROL_EDIT: return CREATE_OUSTRING( "com.sun.star.form.component.TextField" );
+ case API_CONTROL_LISTBOX: return CREATE_OUSTRING( "com.sun.star.form.component.ListBox" );
+ case API_CONTROL_COMBOBOX: return CREATE_OUSTRING( "com.sun.star.form.component.ComboBox" );
+ case API_CONTROL_SPINBUTTON: return CREATE_OUSTRING( "com.sun.star.form.component.SpinButton" );
+ case API_CONTROL_SCROLLBAR: return CREATE_OUSTRING( "com.sun.star.form.component.ScrollBar" );
+ case API_CONTROL_GROUPBOX: return CREATE_OUSTRING( "com.sun.star.form.component.GroupBox" );
+ default: OSL_ENSURE( false, "ControlModelBase::getServiceName - no form component service supported" );
+ }
+ return OUString();
+}
+
+void ControlModelBase::importProperty( sal_Int32 /*nPropId*/, const OUString& /*rValue*/ )
+{
+}
+
+void ControlModelBase::importPictureData( sal_Int32 /*nPropId*/, BinaryInputStream& /*rInStrm*/ )
+{
+}
+
+void ControlModelBase::convertProperties( PropertyMap& /*rPropMap*/, const ControlConverter& /*rConv*/ ) const
+{
+}
+
+void ControlModelBase::convertSize( PropertyMap& rPropMap, const ControlConverter& rConv ) const
+{
+ rConv.convertSize( rPropMap, maSize );
+}
+
+// ============================================================================
+
+ComCtlModelBase::ComCtlModelBase( sal_uInt32 nDataPartId5, sal_uInt32 nDataPartId6,
+ sal_uInt16 nVersion, bool bCommonPart, bool bComplexPart ) :
+ maFontData( CREATE_OUSTRING( "Tahoma" ), 82500 ),
+ mnFlags( 0 ),
+ mnVersion( nVersion ),
+ mnDataPartId5( nDataPartId5 ),
+ mnDataPartId6( nDataPartId6 ),
+ mbCommonPart( bCommonPart ),
+ mbComplexPart( bComplexPart )
+{
+}
+
+bool ComCtlModelBase::importBinaryModel( BinaryInputStream& rInStrm )
+{
+ // read initial size part and header of the control data part
+ if( importSizePart( rInStrm ) && readPartHeader( rInStrm, getDataPartId(), mnVersion ) )
+ {
+ // if flags part exists, the first int32 of the data part contains its size
+ sal_uInt32 nCommonPartSize = mbCommonPart ? rInStrm.readuInt32() : 0;
+ // implementations must read the exact amount of data, stream must point to its end afterwards
+ importControlData( rInStrm );
+ // read following parts
+ if( !rInStrm.isEof() &&
+ (!mbCommonPart || importCommonPart( rInStrm, nCommonPartSize )) &&
+ (!mbComplexPart || importComplexPart( rInStrm )) )
+ {
+ return !rInStrm.isEof();
+ }
+ }
+ return false;
+}
+
+void ComCtlModelBase::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const
+{
+ if( mbCommonPart )
+ rPropMap.setProperty( PROP_Enabled, getFlag( mnFlags, COMCTL_COMMON_ENABLED ) );
+ ControlModelBase::convertProperties( rPropMap, rConv );
+}
+
+void ComCtlModelBase::importCommonExtraData( BinaryInputStream& /*rInStrm*/ )
+{
+}
+
+void ComCtlModelBase::importCommonTrailingData( BinaryInputStream& /*rInStrm*/ )
+{
+}
+
+sal_uInt32 ComCtlModelBase::getDataPartId() const
+{
+ switch( mnVersion )
+ {
+ case 5: return mnDataPartId5;
+ case 6: return mnDataPartId6;
+ }
+ OSL_ENSURE( false, "ComCtlObjectBase::getDataPartId - unxpected version" );
+ return SAL_MAX_UINT32;
+}
+
+bool ComCtlModelBase::readPartHeader( BinaryInputStream& rInStrm, sal_uInt32 nExpPartId, sal_uInt16 nExpMajor, sal_uInt16 nExpMinor )
+{
+ // no idea if all this is correct...
+ sal_uInt32 nPartId;
+ sal_uInt16 nMajor, nMinor;
+ rInStrm >> nPartId >> nMinor >> nMajor;
+ bool bPartId = nPartId == nExpPartId;
+ OSL_ENSURE( bPartId, "ComCtlObjectBase::readPartHeader - unexpected part identifier" );
+ bool bVersion = ((nExpMajor == SAL_MAX_UINT16) || (nExpMajor == nMajor)) && ((nExpMinor == SAL_MAX_UINT16) || (nExpMinor == nMinor));
+ OSL_ENSURE( bVersion, "ComCtlObjectBase::readPartHeader - unexpected part version" );
+ return !rInStrm.isEof() && bPartId && bVersion;
+}
+
+bool ComCtlModelBase::importSizePart( BinaryInputStream& rInStrm )
+{
+ if( readPartHeader( rInStrm, COMCTL_ID_SIZE, 0, 8 ) )
+ {
+ rInStrm >> maSize.first >> maSize.second;
+ return !rInStrm.isEof();
+ }
+ return false;
+}
+
+bool ComCtlModelBase::importCommonPart( BinaryInputStream& rInStrm, sal_uInt32 nPartSize )
+{
+ sal_Int64 nEndPos = rInStrm.tell() + nPartSize;
+ if( (nPartSize >= 16) && readPartHeader( rInStrm, COMCTL_ID_COMMONDATA, 5, 0 ) )
+ {
+ rInStrm.skip( 4 );
+ rInStrm >> mnFlags;
+ // implementations may read less than the exact amount of data
+ importCommonExtraData( rInStrm );
+ rInStrm.seek( nEndPos );
+ // implementations must read the exact amount of data, stream must point to its end afterwards
+ importCommonTrailingData( rInStrm );
+ return !rInStrm.isEof();
+ }
+ return false;
+}
+
+bool ComCtlModelBase::importComplexPart( BinaryInputStream& rInStrm )
+{
+ if( readPartHeader( rInStrm, COMCTL_ID_COMPLEXDATA, 5, 1 ) )
+ {
+ sal_uInt32 nContFlags;
+ rInStrm >> nContFlags;
+ bool bReadOk =
+ (!getFlag( nContFlags, COMCTL_COMPLEX_FONT ) || OleHelper::importStdFont( maFontData, rInStrm, true )) &&
+ (!getFlag( nContFlags, COMCTL_COMPLEX_MOUSEICON ) || OleHelper::importStdPic( maMouseIcon, rInStrm, true ));
+ return bReadOk && !rInStrm.isEof();
+ }
+ return false;
+}
+
+// ============================================================================
+
+ComCtlScrollBarModel::ComCtlScrollBarModel( sal_uInt16 nVersion ) :
+ ComCtlModelBase( SAL_MAX_UINT32, COMCTL_ID_SCROLLBAR_60, nVersion, true, true ),
+ mnScrollBarFlags( 0x00000011 ),
+ mnLargeChange( 1 ),
+ mnSmallChange( 1 ),
+ mnMin( 0 ),
+ mnMax( 32767 ),
+ mnPosition( 0 )
+{
+}
+
+ApiControlType ComCtlScrollBarModel::getControlType() const
+{
+ return API_CONTROL_SCROLLBAR;
+}
+
+void ComCtlScrollBarModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const
+{
+ rPropMap.setProperty( PROP_Border, API_BORDER_NONE );
+ rConv.convertOrientation( rPropMap, getFlag( mnScrollBarFlags, COMCTL_SCROLLBAR_HOR ) );
+ rConv.convertScrollBar( rPropMap, mnMin, mnMax, mnPosition, mnSmallChange, mnLargeChange, mbAwtModel );
+ ComCtlModelBase::convertProperties( rPropMap, rConv );
+}
+
+void ComCtlScrollBarModel::importControlData( BinaryInputStream& rInStrm )
+{
+ rInStrm >> mnScrollBarFlags >> mnLargeChange >> mnSmallChange >> mnMin >> mnMax >> mnPosition;
+}
// ============================================================================
-AxControlModelBase::AxControlModelBase() :
- mnWidth( 0 ),
- mnHeight( 0 )
+ComCtlProgressBarModel::ComCtlProgressBarModel( sal_uInt16 nVersion ) :
+ ComCtlModelBase( COMCTL_ID_PROGRESSBAR_50, COMCTL_ID_PROGRESSBAR_60, nVersion, true, true ),
+ mfMin( 0.0 ),
+ mfMax( 100.0 ),
+ mnVertical( 0 ),
+ mnSmooth( 0 )
{
}
-AxControlModelBase::~AxControlModelBase()
+ApiControlType ComCtlProgressBarModel::getControlType() const
+{
+ return API_CONTROL_PROGRESSBAR;
+}
+
+void ComCtlProgressBarModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const
+{
+ sal_uInt16 nBorder = getFlag( mnFlags, COMCTL_COMMON_3DBORDER ) ? API_BORDER_SUNKEN :
+ (getFlag( mnFlags, COMCTL_COMMON_FLATBORDER ) ? API_BORDER_FLAT : API_BORDER_NONE);
+ rPropMap.setProperty( PROP_Border, nBorder );
+ rPropMap.setProperty( PROP_ProgressValueMin, getLimitedValue< sal_Int32, double >( ::std::min( mfMin, mfMax ), 0.0, SAL_MAX_INT32 ) );
+ rPropMap.setProperty( PROP_ProgressValueMax, getLimitedValue< sal_Int32, double >( ::std::max( mfMin, mfMax ), 0.0, SAL_MAX_INT32 ) );
+ // ComCtl model does not provide current value?
+ ComCtlModelBase::convertProperties( rPropMap, rConv );
+}
+
+void ComCtlProgressBarModel::importControlData( BinaryInputStream& rInStrm )
+{
+ rInStrm >> mfMin >> mfMax;
+ if( mnVersion == 6 )
+ rInStrm >> mnVertical >> mnSmooth;
+}
+
+// ============================================================================
+
+AxControlModelBase::AxControlModelBase()
{
}
@@ -393,33 +668,18 @@ void AxControlModelBase::importProperty( sal_Int32 nPropId, const OUString& rVal
OSL_ENSURE( nSepPos >= 0, "AxControlModelBase::importProperty - missing separator in 'Size' property" );
if( nSepPos >= 0 )
{
- mnWidth = rValue.copy( 0, nSepPos ).toInt32();
- mnHeight = rValue.copy( nSepPos + 1 ).toInt32();
+ maSize.first = rValue.copy( 0, nSepPos ).toInt32();
+ maSize.second = rValue.copy( nSepPos + 1 ).toInt32();
}
}
break;
}
}
-void AxControlModelBase::importBinaryModel( BinaryInputStream& /*rInStrm*/ )
-{
-}
-
-void AxControlModelBase::importPictureData( sal_Int32 /*nPropId*/, BinaryInputStream& /*rInStrm*/ )
-{
-}
-
-void AxControlModelBase::convertProperties( AxControlHelper& /*rHelper*/, PropertyMap& /*rPropMap*/ ) const
-{
-}
-
// ============================================================================
-AxFontDataModel::AxFontDataModel() :
- mnFontEffects( 0 ),
- mnFontHeight( 160 ),
- mnFontCharSet( 1 ),
- mnHorAlign( AX_FONTALIGN_LEFT )
+AxFontDataModel::AxFontDataModel( bool bSupportsAlign ) :
+ mbSupportsAlign( bSupportsAlign )
{
}
@@ -427,70 +687,59 @@ void AxFontDataModel::importProperty( sal_Int32 nPropId, const OUString& rValue
{
switch( nPropId )
{
- case XML_FontName: maFontName = rValue; break;
- case XML_FontEffects: mnFontEffects = AttributeList::decodeUnsigned( rValue ); break;
- case XML_FontHeight: mnFontHeight = AttributeList::decodeInteger( rValue ); break;
- case XML_FontCharSet: mnFontCharSet = AttributeList::decodeInteger( rValue ); break;
- case XML_ParagraphAlign: mnHorAlign = AttributeList::decodeInteger( rValue ); break;
+ case XML_FontName: maFontData.maFontName = rValue; break;
+ case XML_FontEffects: maFontData.mnFontEffects = AttributeList::decodeUnsigned( rValue ); break;
+ case XML_FontHeight: maFontData.mnFontHeight = AttributeList::decodeInteger( rValue ); break;
+ case XML_FontCharSet: maFontData.mnFontCharSet = AttributeList::decodeInteger( rValue ); break;
+ case XML_ParagraphAlign: maFontData.mnHorAlign = AttributeList::decodeInteger( rValue ); break;
default: AxControlModelBase::importProperty( nPropId, rValue );
}
}
-void AxFontDataModel::importBinaryModel( BinaryInputStream& rInStrm )
+bool AxFontDataModel::importBinaryModel( BinaryInputStream& rInStrm )
{
- AxBinaryPropertyReader aReader( rInStrm );
- aReader.readStringProperty( maFontName );
- aReader.readIntProperty< sal_uInt32 >( mnFontEffects );
- aReader.readIntProperty< sal_Int32 >( mnFontHeight );
- aReader.skipIntProperty< sal_Int32 >(); // font offset
- aReader.readIntProperty< sal_uInt8 >( mnFontCharSet );
- aReader.skipIntProperty< sal_uInt8 >(); // font pitch/family
- aReader.readIntProperty< sal_uInt8 >( mnHorAlign );
- aReader.skipIntProperty< sal_uInt16 >(); // font weight
- aReader.finalizeImport();
+ return maFontData.importBinaryModel( rInStrm );
}
-void AxFontDataModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const
+void AxFontDataModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const
{
namespace cssa = ::com::sun::star::awt;
// font name
- if( maFontName.getLength() > 0 )
- rPropMap.setProperty( PROP_FontName, maFontName );
+ if( maFontData.maFontName.getLength() > 0 )
+ rPropMap.setProperty( PROP_FontName, maFontData.maFontName );
// font effects
- rPropMap.setProperty( PROP_FontWeight, getFlagValue( mnFontEffects, AX_FONT_BOLD, cssa::FontWeight::BOLD, cssa::FontWeight::NORMAL ) );
- rPropMap.setProperty( PROP_FontSlant, getFlagValue< sal_Int16 >( mnFontEffects, AX_FONT_ITALIC, cssa::FontSlant_ITALIC, cssa::FontSlant_NONE ) );
- rPropMap.setProperty( PROP_FontUnderline, getFlagValue( mnFontEffects, AX_FONT_UNDERLINE, cssa::FontUnderline::SINGLE, cssa::FontUnderline::NONE ) );
- rPropMap.setProperty( PROP_FontStrikeout, getFlagValue( mnFontEffects, AX_FONT_STRIKEOUT, cssa::FontStrikeout::SINGLE, cssa::FontStrikeout::NONE ) );
-
- /* font height in points. MSO uses weird font sizes:
- 1pt->30, 2pt->45, 3pt->60, 4pt->75, 5pt->105, 6pt->120, 7pt->135,
- 8pt->165, 9pt->180, 10pt->195, 11pt->225, ... */
- sal_Int16 nHeight = getLimitedValue< sal_Int16, sal_Int32 >( (mnFontHeight + 10) / 20, 1, SAL_MAX_INT16 );
- rPropMap.setProperty( PROP_FontHeight, nHeight );
+ rPropMap.setProperty( PROP_FontWeight, getFlagValue( maFontData.mnFontEffects, AX_FONTDATA_BOLD, cssa::FontWeight::BOLD, cssa::FontWeight::NORMAL ) );
+ rPropMap.setProperty( PROP_FontSlant, getFlagValue< sal_Int16 >( maFontData.mnFontEffects, AX_FONTDATA_ITALIC, cssa::FontSlant_ITALIC, cssa::FontSlant_NONE ) );
+ rPropMap.setProperty( PROP_FontUnderline, getFlagValue( maFontData.mnFontEffects, AX_FONTDATA_UNDERLINE, cssa::FontUnderline::SINGLE, cssa::FontUnderline::NONE ) );
+ rPropMap.setProperty( PROP_FontStrikeout, getFlagValue( maFontData.mnFontEffects, AX_FONTDATA_STRIKEOUT, cssa::FontStrikeout::SINGLE, cssa::FontStrikeout::NONE ) );
+ rPropMap.setProperty( PROP_FontHeight, maFontData.getHeightPoints() );
// font character set
rtl_TextEncoding eFontEnc = RTL_TEXTENCODING_DONTKNOW;
- if( (0 <= mnFontCharSet) && (mnFontCharSet <= SAL_MAX_UINT8) )
- eFontEnc = rtl_getTextEncodingFromWindowsCharset( static_cast< sal_uInt8 >( mnFontCharSet ) );
+ if( (0 <= maFontData.mnFontCharSet) && (maFontData.mnFontCharSet <= SAL_MAX_UINT8) )
+ eFontEnc = rtl_getTextEncodingFromWindowsCharset( static_cast< sal_uInt8 >( maFontData.mnFontCharSet ) );
if( eFontEnc != RTL_TEXTENCODING_DONTKNOW )
rPropMap.setProperty( PROP_FontCharset, static_cast< sal_Int16 >( eFontEnc ) );
// text alignment
- sal_Int32 nAlign = cssa::TextAlign::LEFT;
- switch( mnHorAlign )
+ if( mbSupportsAlign )
{
- case AX_FONTALIGN_LEFT: nAlign = cssa::TextAlign::LEFT; break;
- case AX_FONTALIGN_RIGHT: nAlign = cssa::TextAlign::RIGHT; break;
- case AX_FONTALIGN_CENTER: nAlign = cssa::TextAlign::CENTER; break;
- default: OSL_ENSURE( false, "AxFontDataModel::convertProperties - unknown text alignment" );
+ sal_Int32 nAlign = cssa::TextAlign::LEFT;
+ switch( maFontData.mnHorAlign )
+ {
+ case AX_FONTDATA_LEFT: nAlign = cssa::TextAlign::LEFT; break;
+ case AX_FONTDATA_RIGHT: nAlign = cssa::TextAlign::RIGHT; break;
+ case AX_FONTDATA_CENTER: nAlign = cssa::TextAlign::CENTER; break;
+ default: OSL_ENSURE( false, "AxFontDataModel::convertProperties - unknown text alignment" );
+ }
+ // form controls expect short value
+ rPropMap.setProperty( PROP_Align, static_cast< sal_Int16 >( nAlign ) );
}
- // form controls expect short value
- rPropMap.setProperty( PROP_Align, static_cast< sal_Int16 >( nAlign ) );
// process base class properties
- AxControlModelBase::convertProperties( rHelper, rPropMap );
+ AxControlModelBase::convertProperties( rPropMap, rConv );
}
// ============================================================================
@@ -527,7 +776,7 @@ void AxCommandButtonModel::importPictureData( sal_Int32 nPropId, BinaryInputStre
}
}
-void AxCommandButtonModel::importBinaryModel( BinaryInputStream& rInStrm )
+bool AxCommandButtonModel::importBinaryModel( BinaryInputStream& rInStrm )
{
AxBinaryPropertyReader aReader( rInStrm );
aReader.readIntProperty< sal_uInt32 >( mnTextColor );
@@ -535,32 +784,31 @@ void AxCommandButtonModel::importBinaryModel( BinaryInputStream& rInStrm )
aReader.readIntProperty< sal_uInt32 >( mnFlags );
aReader.readStringProperty( maCaption );
aReader.readIntProperty< sal_uInt32 >( mnPicturePos );
- aReader.readPairProperty( mnWidth, mnHeight );
+ aReader.readPairProperty( maSize );
aReader.skipIntProperty< sal_uInt8 >(); // mouse pointer
aReader.readPictureProperty( maPictureData );
aReader.skipIntProperty< sal_uInt16 >(); // accelerator
aReader.readBoolProperty( mbFocusOnClick, true ); // binary flag means "do not take focus"
aReader.skipPictureProperty(); // mouse icon
- if( aReader.finalizeImport() )
- AxFontDataModel::importBinaryModel( rInStrm );
+ return aReader.finalizeImport() && AxFontDataModel::importBinaryModel( rInStrm );
}
-OUString AxCommandButtonModel::getServiceName() const
+ApiControlType AxCommandButtonModel::getControlType() const
{
- return CREATE_OUSTRING( "com.sun.star.form.component.CommandButton" );
+ return API_CONTROL_BUTTON;
}
-void AxCommandButtonModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const
+void AxCommandButtonModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const
{
rPropMap.setProperty( PROP_Label, maCaption );
- rPropMap.setProperty( PROP_TextColor, rHelper.convertColor( mnTextColor ) );
rPropMap.setProperty( PROP_Enabled, getFlag( mnFlags, AX_FLAGS_ENABLED ) );
rPropMap.setProperty( PROP_MultiLine, getFlag( mnFlags, AX_FLAGS_WORDWRAP ) );
rPropMap.setProperty( PROP_FocusOnClick, mbFocusOnClick );
rPropMap.setProperty( PROP_VerticalAlign, ::com::sun::star::style::VerticalAlignment_MIDDLE );
- lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_NOTSUPPORTED );
- lclConvertPicture( rHelper, rPropMap, maPictureData, mnPicturePos );
- AxFontDataModel::convertProperties( rHelper, rPropMap );
+ rConv.convertColor( rPropMap, PROP_TextColor, mnTextColor );
+ rConv.convertAxBackground( rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_NOTSUPPORTED );
+ rConv.convertAxPicture( rPropMap, maPictureData, mnPicturePos );
+ AxFontDataModel::convertProperties( rPropMap, rConv );
}
// ============================================================================
@@ -590,7 +838,7 @@ void AxLabelModel::importProperty( sal_Int32 nPropId, const OUString& rValue )
}
}
-void AxLabelModel::importBinaryModel( BinaryInputStream& rInStrm )
+bool AxLabelModel::importBinaryModel( BinaryInputStream& rInStrm )
{
AxBinaryPropertyReader aReader( rInStrm );
aReader.readIntProperty< sal_uInt32 >( mnTextColor );
@@ -598,7 +846,7 @@ void AxLabelModel::importBinaryModel( BinaryInputStream& rInStrm )
aReader.readIntProperty< sal_uInt32 >( mnFlags );
aReader.readStringProperty( maCaption );
aReader.skipIntProperty< sal_uInt32 >(); // picture position
- aReader.readPairProperty( mnWidth, mnHeight );
+ aReader.readPairProperty( maSize );
aReader.skipIntProperty< sal_uInt8 >(); // mouse pointer
aReader.readIntProperty< sal_uInt32 >( mnBorderColor );
aReader.readIntProperty< sal_uInt16 >( mnBorderStyle );
@@ -606,25 +854,24 @@ void AxLabelModel::importBinaryModel( BinaryInputStream& rInStrm )
aReader.skipPictureProperty(); // picture
aReader.skipIntProperty< sal_uInt16 >(); // accelerator
aReader.skipPictureProperty(); // mouse icon
- if( aReader.finalizeImport() )
- AxFontDataModel::importBinaryModel( rInStrm );
+ return aReader.finalizeImport() && AxFontDataModel::importBinaryModel( rInStrm );
}
-OUString AxLabelModel::getServiceName() const
+ApiControlType AxLabelModel::getControlType() const
{
- return CREATE_OUSTRING( "com.sun.star.form.component.FixedText" );
+ return API_CONTROL_FIXEDTEXT;
}
-void AxLabelModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const
+void AxLabelModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const
{
rPropMap.setProperty( PROP_Label, maCaption );
- rPropMap.setProperty( PROP_TextColor, rHelper.convertColor( mnTextColor ) );
rPropMap.setProperty( PROP_Enabled, getFlag( mnFlags, AX_FLAGS_ENABLED ) );
rPropMap.setProperty( PROP_MultiLine, getFlag( mnFlags, AX_FLAGS_WORDWRAP ) );
rPropMap.setProperty( PROP_VerticalAlign, ::com::sun::star::style::VerticalAlignment_TOP );
- lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID );
- lclConvertBorder( rHelper, rPropMap, mnBorderColor, mnBorderStyle, mnSpecialEffect );
- AxFontDataModel::convertProperties( rHelper, rPropMap );
+ rConv.convertColor( rPropMap, PROP_TextColor, mnTextColor );
+ rConv.convertAxBackground( rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID );
+ rConv.convertAxBorder( rPropMap, mnBorderColor, mnBorderStyle, mnSpecialEffect );
+ AxFontDataModel::convertProperties( rPropMap, rConv );
}
// ============================================================================
@@ -666,7 +913,7 @@ void AxImageModel::importPictureData( sal_Int32 nPropId, BinaryInputStream& rInS
}
}
-void AxImageModel::importBinaryModel( BinaryInputStream& rInStrm )
+bool AxImageModel::importBinaryModel( BinaryInputStream& rInStrm )
{
AxBinaryPropertyReader aReader( rInStrm );
aReader.skipUndefinedProperty();
@@ -678,32 +925,32 @@ void AxImageModel::importBinaryModel( BinaryInputStream& rInStrm )
aReader.skipIntProperty< sal_uInt8 >(); // mouse pointer
aReader.readIntProperty< sal_uInt8 >( mnPicSizeMode );
aReader.readIntProperty< sal_uInt8 >( mnSpecialEffect );
- aReader.readPairProperty( mnWidth, mnHeight );
+ aReader.readPairProperty( maSize );
aReader.readPictureProperty( maPictureData );
aReader.readIntProperty< sal_uInt8 >( mnPicAlign );
aReader.readBoolProperty( mbPicTiling );
aReader.readIntProperty< sal_uInt32 >( mnFlags );
aReader.skipPictureProperty(); // mouse icon
- aReader.finalizeImport();
+ return aReader.finalizeImport();
}
-OUString AxImageModel::getServiceName() const
+ApiControlType AxImageModel::getControlType() const
{
- return CREATE_OUSTRING( "com.sun.star.form.component.DatabaseImageControl" );
+ return API_CONTROL_IMAGE;
}
-void AxImageModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const
+void AxImageModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const
{
rPropMap.setProperty( PROP_Enabled, getFlag( mnFlags, AX_FLAGS_ENABLED ) );
- lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID );
- lclConvertBorder( rHelper, rPropMap, mnBorderColor, mnBorderStyle, mnSpecialEffect );
- lclConvertPicture( rHelper, rPropMap, maPictureData, mnPicSizeMode, mnPicAlign, mbPicTiling );
- AxControlModelBase::convertProperties( rHelper, rPropMap );
+ rConv.convertAxBackground( rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID );
+ rConv.convertAxBorder( rPropMap, mnBorderColor, mnBorderStyle, mnSpecialEffect );
+ rConv.convertAxPicture( rPropMap, maPictureData, mnPicSizeMode, mnPicAlign, mbPicTiling );
+ AxControlModelBase::convertProperties( rPropMap, rConv );
}
// ============================================================================
-AxMorphDataModel::AxMorphDataModel() :
+AxMorphDataModelBase::AxMorphDataModelBase() :
mnTextColor( AX_SYSCOLOR_WINDOWTEXT ),
mnBackColor( AX_SYSCOLOR_WINDOWBACK ),
mnFlags( AX_MORPHDATA_DEFFLAGS ),
@@ -722,7 +969,7 @@ AxMorphDataModel::AxMorphDataModel() :
{
}
-void AxMorphDataModel::importProperty( sal_Int32 nPropId, const OUString& rValue )
+void AxMorphDataModelBase::importProperty( sal_Int32 nPropId, const OUString& rValue )
{
switch( nPropId )
{
@@ -748,7 +995,7 @@ void AxMorphDataModel::importProperty( sal_Int32 nPropId, const OUString& rValue
}
}
-void AxMorphDataModel::importPictureData( sal_Int32 nPropId, BinaryInputStream& rInStrm )
+void AxMorphDataModelBase::importPictureData( sal_Int32 nPropId, BinaryInputStream& rInStrm )
{
switch( nPropId )
{
@@ -757,7 +1004,7 @@ void AxMorphDataModel::importPictureData( sal_Int32 nPropId, BinaryInputStream&
}
}
-void AxMorphDataModel::importBinaryModel( BinaryInputStream& rInStrm )
+bool AxMorphDataModelBase::importBinaryModel( BinaryInputStream& rInStrm )
{
AxBinaryPropertyReader aReader( rInStrm, true );
aReader.readIntProperty< sal_uInt32 >( mnFlags );
@@ -768,7 +1015,7 @@ void AxMorphDataModel::importBinaryModel( BinaryInputStream& rInStrm )
aReader.readIntProperty< sal_uInt8 >( mnScrollBars );
aReader.readIntProperty< sal_uInt8 >( mnDisplayStyle );
aReader.skipIntProperty< sal_uInt8 >(); // mouse pointer
- aReader.readPairProperty( mnWidth, mnHeight );
+ aReader.readPairProperty( maSize );
aReader.readIntProperty< sal_uInt16 >( mnPasswordChar );
aReader.skipIntProperty< sal_uInt32 >(); // list width
aReader.skipIntProperty< sal_uInt16 >(); // bound column
@@ -793,15 +1040,14 @@ void AxMorphDataModel::importBinaryModel( BinaryInputStream& rInStrm )
aReader.skipUndefinedProperty();
aReader.skipBoolProperty();
aReader.readStringProperty( maGroupName );
- if( aReader.finalizeImport() )
- AxFontDataModel::importBinaryModel( rInStrm );
+ return aReader.finalizeImport() && AxFontDataModel::importBinaryModel( rInStrm );
}
-void AxMorphDataModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const
+void AxMorphDataModelBase::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const
{
- rPropMap.setProperty( PROP_TextColor, rHelper.convertColor( mnTextColor ) );
rPropMap.setProperty( PROP_Enabled, getFlag( mnFlags, AX_FLAGS_ENABLED ) );
- AxFontDataModel::convertProperties( rHelper, rPropMap );
+ rConv.convertColor( rPropMap, PROP_TextColor, mnTextColor );
+ AxFontDataModel::convertProperties( rPropMap, rConv );
}
// ============================================================================
@@ -810,22 +1056,22 @@ AxToggleButtonModel::AxToggleButtonModel()
{
}
-OUString AxToggleButtonModel::getServiceName() const
+ApiControlType AxToggleButtonModel::getControlType() const
{
- OSL_ENSURE( mnDisplayStyle == AX_DISPLAYSTYLE_TOGGLE, "AxToggleButtonModel::getServiceName - invalid control type" );
- return CREATE_OUSTRING( "com.sun.star.form.component.CommandButton" );
+ OSL_ENSURE( mnDisplayStyle == AX_DISPLAYSTYLE_TOGGLE, "AxToggleButtonModel::getControlType - invalid control type" );
+ return API_CONTROL_BUTTON;
}
-void AxToggleButtonModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const
+void AxToggleButtonModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const
{
rPropMap.setProperty( PROP_Label, maCaption );
rPropMap.setProperty( PROP_MultiLine, getFlag( mnFlags, AX_FLAGS_WORDWRAP ) );
rPropMap.setProperty( PROP_VerticalAlign, ::com::sun::star::style::VerticalAlignment_MIDDLE );
rPropMap.setProperty( PROP_Toggle, true );
- lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_NOTSUPPORTED );
- lclConvertPicture( rHelper, rPropMap, maPictureData, mnPicturePos );
- lclConvertState( rHelper, rPropMap, maValue, mnMultiSelect, API_DEFAULTSTATE_BOOLEAN );
- AxMorphDataModel::convertProperties( rHelper, rPropMap );
+ rConv.convertAxBackground( rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_NOTSUPPORTED );
+ rConv.convertAxPicture( rPropMap, maPictureData, mnPicturePos );
+ rConv.convertAxState( rPropMap, maValue, mnMultiSelect, API_DEFAULTSTATE_BOOLEAN, mbAwtModel );
+ AxMorphDataModelBase::convertProperties( rPropMap, rConv );
}
// ============================================================================
@@ -834,22 +1080,22 @@ AxCheckBoxModel::AxCheckBoxModel()
{
}
-OUString AxCheckBoxModel::getServiceName() const
+ApiControlType AxCheckBoxModel::getControlType() const
{
- OSL_ENSURE( mnDisplayStyle == AX_DISPLAYSTYLE_CHECKBOX, "AxCheckBoxModel::getServiceName - invalid control type" );
- return CREATE_OUSTRING( "com.sun.star.form.component.CheckBox" );
+ OSL_ENSURE( mnDisplayStyle == AX_DISPLAYSTYLE_CHECKBOX, "AxCheckBoxModel::getControlType - invalid control type" );
+ return API_CONTROL_CHECKBOX;
}
-void AxCheckBoxModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const
+void AxCheckBoxModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const
{
rPropMap.setProperty( PROP_Label, maCaption );
rPropMap.setProperty( PROP_MultiLine, getFlag( mnFlags, AX_FLAGS_WORDWRAP ) );
rPropMap.setProperty( PROP_VerticalAlign, ::com::sun::star::style::VerticalAlignment_MIDDLE );
- lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID );
- lclConvertVisualEffect( rHelper, rPropMap, mnSpecialEffect );
- lclConvertPicture( rHelper, rPropMap, maPictureData, mnPicturePos );
- lclConvertState( rHelper, rPropMap, maValue, mnMultiSelect, API_DEFAULTSTATE_TRISTATE );
- AxMorphDataModel::convertProperties( rHelper, rPropMap );
+ rConv.convertAxBackground( rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID );
+ rConv.convertAxVisualEffect( rPropMap, mnSpecialEffect );
+ rConv.convertAxPicture( rPropMap, maPictureData, mnPicturePos );
+ rConv.convertAxState( rPropMap, maValue, mnMultiSelect, API_DEFAULTSTATE_TRISTATE, mbAwtModel );
+ AxMorphDataModelBase::convertProperties( rPropMap, rConv );
}
// ============================================================================
@@ -858,22 +1104,22 @@ AxOptionButtonModel::AxOptionButtonModel()
{
}
-OUString AxOptionButtonModel::getServiceName() const
+ApiControlType AxOptionButtonModel::getControlType() const
{
- OSL_ENSURE( mnDisplayStyle == AX_DISPLAYSTYLE_OPTBUTTON, "AxOptionButtonModel::getServiceName - invalid control type" );
- return CREATE_OUSTRING( "com.sun.star.form.component.RadioButton" );
+ OSL_ENSURE( mnDisplayStyle == AX_DISPLAYSTYLE_OPTBUTTON, "AxOptionButtonModel::getControlType - invalid control type" );
+ return API_CONTROL_RADIOBUTTON;
}
-void AxOptionButtonModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const
+void AxOptionButtonModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const
{
rPropMap.setProperty( PROP_Label, maCaption );
rPropMap.setProperty( PROP_MultiLine, getFlag( mnFlags, AX_FLAGS_WORDWRAP ) );
rPropMap.setProperty( PROP_VerticalAlign, ::com::sun::star::style::VerticalAlignment_MIDDLE );
- lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID );
- lclConvertVisualEffect( rHelper, rPropMap, mnSpecialEffect );
- lclConvertPicture( rHelper, rPropMap, maPictureData, mnPicturePos );
- lclConvertState( rHelper, rPropMap, maValue, mnMultiSelect, API_DEFAULTSTATE_SHORT );
- AxMorphDataModel::convertProperties( rHelper, rPropMap );
+ rConv.convertAxBackground( rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID );
+ rConv.convertAxVisualEffect( rPropMap, mnSpecialEffect );
+ rConv.convertAxPicture( rPropMap, maPictureData, mnPicturePos );
+ rConv.convertAxState( rPropMap, maValue, mnMultiSelect, API_DEFAULTSTATE_SHORT, mbAwtModel );
+ AxMorphDataModelBase::convertProperties( rPropMap, rConv );
}
// ============================================================================
@@ -882,25 +1128,25 @@ AxTextBoxModel::AxTextBoxModel()
{
}
-OUString AxTextBoxModel::getServiceName() const
+ApiControlType AxTextBoxModel::getControlType() const
{
- OSL_ENSURE( mnDisplayStyle == AX_DISPLAYSTYLE_TEXT, "AxTextBoxModel::getServiceName - invalid control type" );
- return CREATE_OUSTRING( "com.sun.star.form.component.TextField" );
+ OSL_ENSURE( mnDisplayStyle == AX_DISPLAYSTYLE_TEXT, "AxTextBoxModel::getControlType - invalid control type" );
+ return API_CONTROL_EDIT;
}
-void AxTextBoxModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const
+void AxTextBoxModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const
{
rPropMap.setProperty( PROP_MultiLine, getFlag( mnFlags, AX_FLAGS_MULTILINE ) );
rPropMap.setProperty( PROP_HideInactiveSelection, getFlag( mnFlags, AX_FLAGS_HIDESELECTION ) );
- rPropMap.setProperty( PROP_DefaultText, maValue );
+ rPropMap.setProperty( mbAwtModel ? PROP_Text : PROP_DefaultText, maValue );
rPropMap.setProperty( PROP_MaxTextLen, getLimitedValue< sal_Int16, sal_Int32 >( mnMaxLength, 0, SAL_MAX_INT16 ) );
if( (0 < mnPasswordChar) && (mnPasswordChar <= SAL_MAX_INT16) )
rPropMap.setProperty( PROP_EchoChar, static_cast< sal_Int16 >( mnPasswordChar ) );
rPropMap.setProperty( PROP_HScroll, getFlag( mnScrollBars, AX_SCROLLBAR_HORIZONTAL ) );
rPropMap.setProperty( PROP_VScroll, getFlag( mnScrollBars, AX_SCROLLBAR_VERTICAL ) );
- lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID );
- lclConvertBorder( rHelper, rPropMap, mnBorderColor, mnBorderStyle, mnSpecialEffect );
- AxMorphDataModel::convertProperties( rHelper, rPropMap );
+ rConv.convertAxBackground( rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID );
+ rConv.convertAxBorder( rPropMap, mnBorderColor, mnBorderStyle, mnSpecialEffect );
+ AxMorphDataModelBase::convertProperties( rPropMap, rConv );
}
// ============================================================================
@@ -909,20 +1155,20 @@ AxListBoxModel::AxListBoxModel()
{
}
-OUString AxListBoxModel::getServiceName() const
+ApiControlType AxListBoxModel::getControlType() const
{
- OSL_ENSURE( mnDisplayStyle == AX_DISPLAYSTYLE_LISTBOX, "AxListBoxModel::getServiceName - invalid control type" );
- return CREATE_OUSTRING( "com.sun.star.form.component.ListBox" );
+ OSL_ENSURE( mnDisplayStyle == AX_DISPLAYSTYLE_LISTBOX, "AxListBoxModel::getControlType - invalid control type" );
+ return API_CONTROL_LISTBOX;
}
-void AxListBoxModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const
+void AxListBoxModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const
{
bool bMultiSelect = (mnMultiSelect == AX_SELCTION_MULTI) || (mnMultiSelect == AX_SELCTION_EXTENDED);
rPropMap.setProperty( PROP_MultiSelection, bMultiSelect );
rPropMap.setProperty( PROP_Dropdown, false );
- lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID );
- lclConvertBorder( rHelper, rPropMap, mnBorderColor, mnBorderStyle, mnSpecialEffect );
- AxMorphDataModel::convertProperties( rHelper, rPropMap );
+ rConv.convertAxBackground( rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID );
+ rConv.convertAxBorder( rPropMap, mnBorderColor, mnBorderStyle, mnSpecialEffect );
+ AxMorphDataModelBase::convertProperties( rPropMap, rConv );
}
// ============================================================================
@@ -931,18 +1177,18 @@ AxComboBoxModel::AxComboBoxModel()
{
}
-OUString AxComboBoxModel::getServiceName() const
+ApiControlType AxComboBoxModel::getControlType() const
{
- OSL_ENSURE( (mnDisplayStyle == AX_DISPLAYSTYLE_COMBOBOX) || (mnDisplayStyle == AX_DISPLAYSTYLE_DROPDOWN), "AxComboBoxModel::getServiceName - invalid control type" );
- return (mnDisplayStyle == AX_DISPLAYSTYLE_DROPDOWN) ? CREATE_OUSTRING( "com.sun.star.form.component.ListBox" ) : CREATE_OUSTRING( "com.sun.star.form.component.ComboBox" );
+ OSL_ENSURE( (mnDisplayStyle == AX_DISPLAYSTYLE_COMBOBOX) || (mnDisplayStyle == AX_DISPLAYSTYLE_DROPDOWN), "AxComboBoxModel::getControlType - invalid control type" );
+ return (mnDisplayStyle == AX_DISPLAYSTYLE_DROPDOWN) ? API_CONTROL_LISTBOX : API_CONTROL_COMBOBOX;
}
-void AxComboBoxModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const
+void AxComboBoxModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const
{
if( mnDisplayStyle != AX_DISPLAYSTYLE_DROPDOWN )
{
rPropMap.setProperty( PROP_HideInactiveSelection, getFlag( mnFlags, AX_FLAGS_HIDESELECTION ) );
- rPropMap.setProperty( PROP_DefaultText, maValue );
+ rPropMap.setProperty( mbAwtModel ? PROP_Text : PROP_DefaultText, maValue );
rPropMap.setProperty( PROP_MaxTextLen, getLimitedValue< sal_Int16, sal_Int32 >( mnMaxLength, 0, SAL_MAX_INT16 ) );
bool bAutoComplete = (mnMatchEntry == AX_MATCHENTRY_FIRSTLETTER) || (mnMatchEntry == AX_MATCHENTRY_COMPLETE);
rPropMap.setProperty( PROP_Autocomplete, bAutoComplete );
@@ -950,9 +1196,9 @@ void AxComboBoxModel::convertProperties( AxControlHelper& rHelper, PropertyMap&
bool bShowDropdown = (mnShowDropButton == AX_SHOWDROPBUTTON_FOCUS) || (mnShowDropButton == AX_SHOWDROPBUTTON_ALWAYS);
rPropMap.setProperty( PROP_Dropdown, bShowDropdown );
rPropMap.setProperty( PROP_LineCount, getLimitedValue< sal_Int16, sal_Int32 >( mnListRows, 1, SAL_MAX_INT16 ) );
- lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID );
- lclConvertBorder( rHelper, rPropMap, mnBorderColor, mnBorderStyle, mnSpecialEffect );
- AxMorphDataModel::convertProperties( rHelper, rPropMap );
+ rConv.convertAxBackground( rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_VOID );
+ rConv.convertAxBorder( rPropMap, mnBorderColor, mnBorderStyle, mnSpecialEffect );
+ AxMorphDataModelBase::convertProperties( rPropMap, rConv );
}
// ============================================================================
@@ -970,9 +1216,9 @@ AxSpinButtonModel::AxSpinButtonModel() :
{
}
-OUString AxSpinButtonModel::getServiceName() const
+ApiControlType AxSpinButtonModel::getControlType() const
{
- return CREATE_OUSTRING( "com.sun.star.form.component.SpinButton" );
+ return API_CONTROL_SPINBUTTON;
}
void AxSpinButtonModel::importProperty( sal_Int32 nPropId, const OUString& rValue )
@@ -992,13 +1238,13 @@ void AxSpinButtonModel::importProperty( sal_Int32 nPropId, const OUString& rValu
}
}
-void AxSpinButtonModel::importBinaryModel( BinaryInputStream& rInStrm )
+bool AxSpinButtonModel::importBinaryModel( BinaryInputStream& rInStrm )
{
AxBinaryPropertyReader aReader( rInStrm );
aReader.readIntProperty< sal_uInt32 >( mnArrowColor );
aReader.readIntProperty< sal_uInt32 >( mnBackColor );
aReader.readIntProperty< sal_uInt32 >( mnFlags );
- aReader.readPairProperty( mnWidth, mnHeight );
+ aReader.readPairProperty( maSize );
aReader.skipIntProperty< sal_uInt32 >(); // unused
aReader.readIntProperty< sal_Int32 >( mnMin );
aReader.readIntProperty< sal_Int32 >( mnMax );
@@ -1010,25 +1256,25 @@ void AxSpinButtonModel::importBinaryModel( BinaryInputStream& rInStrm )
aReader.readIntProperty< sal_Int32 >( mnDelay );
aReader.skipPictureProperty(); // mouse icon
aReader.skipIntProperty< sal_uInt8 >(); // mouse pointer
- aReader.finalizeImport();
+ return aReader.finalizeImport();
}
-void AxSpinButtonModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const
+void AxSpinButtonModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const
{
sal_Int32 nMin = ::std::min( mnMin, mnMax );
sal_Int32 nMax = ::std::max( mnMin, mnMax );
- rPropMap.setProperty( PROP_SymbolColor, rHelper.convertColor( mnArrowColor ) );
rPropMap.setProperty( PROP_Enabled, getFlag( mnFlags, AX_FLAGS_ENABLED ) );
rPropMap.setProperty( PROP_SpinValueMin, nMin );
rPropMap.setProperty( PROP_SpinValueMax, nMax );
rPropMap.setProperty( PROP_SpinIncrement, mnSmallChange );
- rPropMap.setProperty( PROP_DefaultSpinValue, mnPosition );
+ rPropMap.setProperty( mbAwtModel ? PROP_SpinValue : PROP_DefaultSpinValue, mnPosition );
rPropMap.setProperty( PROP_Repeat, true );
rPropMap.setProperty( PROP_RepeatDelay, mnDelay );
rPropMap.setProperty( PROP_Border, API_BORDER_NONE );
- lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_NOTSUPPORTED );
- lclConvertOrientation( rHelper, rPropMap, mnOrientation, mnWidth, mnHeight );
- AxControlModelBase::convertProperties( rHelper, rPropMap );
+ rConv.convertColor( rPropMap, PROP_SymbolColor, mnArrowColor );
+ rConv.convertAxBackground( rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_NOTSUPPORTED );
+ rConv.convertAxOrientation( rPropMap, maSize, mnOrientation );
+ AxControlModelBase::convertProperties( rPropMap, rConv );
}
// ============================================================================
@@ -1048,9 +1294,9 @@ AxScrollBarModel::AxScrollBarModel() :
{
}
-OUString AxScrollBarModel::getServiceName() const
+ApiControlType AxScrollBarModel::getControlType() const
{
- return CREATE_OUSTRING( "com.sun.star.form.component.ScrollBar" );
+ return API_CONTROL_SCROLLBAR;
}
void AxScrollBarModel::importProperty( sal_Int32 nPropId, const OUString& rValue )
@@ -1072,13 +1318,13 @@ void AxScrollBarModel::importProperty( sal_Int32 nPropId, const OUString& rValue
}
}
-void AxScrollBarModel::importBinaryModel( BinaryInputStream& rInStrm )
+bool AxScrollBarModel::importBinaryModel( BinaryInputStream& rInStrm )
{
AxBinaryPropertyReader aReader( rInStrm );
aReader.readIntProperty< sal_uInt32 >( mnArrowColor );
aReader.readIntProperty< sal_uInt32 >( mnBackColor );
aReader.readIntProperty< sal_uInt32 >( mnFlags );
- aReader.readPairProperty( mnWidth, mnHeight );
+ aReader.readPairProperty( maSize );
aReader.skipIntProperty< sal_uInt8 >(); // mouse pointer
aReader.readIntProperty< sal_Int32 >( mnMin );
aReader.readIntProperty< sal_Int32 >( mnMax );
@@ -1092,114 +1338,292 @@ void AxScrollBarModel::importBinaryModel( BinaryInputStream& rInStrm )
aReader.readIntProperty< sal_Int16 >( mnPropThumb );
aReader.readIntProperty< sal_Int32 >( mnDelay );
aReader.skipPictureProperty(); // mouse icon
- aReader.finalizeImport();
+ return aReader.finalizeImport();
}
-void AxScrollBarModel::convertProperties( AxControlHelper& rHelper, PropertyMap& rPropMap ) const
+void AxScrollBarModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const
{
- sal_Int32 nMin = ::std::min( mnMin, mnMax );
- sal_Int32 nMax = ::std::max( mnMin, mnMax );
- rPropMap.setProperty( PROP_SymbolColor, rHelper.convertColor( mnArrowColor ) );
rPropMap.setProperty( PROP_Enabled, getFlag( mnFlags, AX_FLAGS_ENABLED ) );
- rPropMap.setProperty( PROP_ScrollValueMin, nMin );
- rPropMap.setProperty( PROP_ScrollValueMax, nMax );
- rPropMap.setProperty( PROP_LineIncrement, mnSmallChange );
- rPropMap.setProperty( PROP_BlockIncrement, mnLargeChange );
- rPropMap.setProperty( PROP_DefaultScrollValue, mnPosition );
rPropMap.setProperty( PROP_RepeatDelay, mnDelay );
rPropMap.setProperty( PROP_Border, API_BORDER_NONE );
- if( (mnPropThumb == AX_PROPTHUMB_ON) && (nMin < nMax) && (mnLargeChange > 0) )
+ if( (mnPropThumb == AX_PROPTHUMB_ON) && (mnMin != mnMax) && (mnLargeChange > 0) )
{
- double fInterval = nMax - nMin; // prevent integer overflow (fInterval+mnLargeChange may become 0 when int is used)
+ // use double to prevent integer overflow in division (fInterval+mnLargeChange may become 0 when performed as int)
+ double fInterval = fabs( static_cast< double >( mnMax - mnMin ) );
sal_Int32 nThumbLen = getLimitedValue< sal_Int32, double >( (fInterval * mnLargeChange) / (fInterval + mnLargeChange), 1, SAL_MAX_INT32 );
rPropMap.setProperty( PROP_VisibleSize, nThumbLen );
}
- lclConvertBackground( rHelper, rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_NOTSUPPORTED );
- lclConvertOrientation( rHelper, rPropMap, mnOrientation, mnWidth, mnHeight );
- AxControlModelBase::convertProperties( rHelper, rPropMap );
+ rConv.convertColor( rPropMap, PROP_SymbolColor, mnArrowColor );
+ rConv.convertAxBackground( rPropMap, mnBackColor, mnFlags, API_TRANSPARENCY_NOTSUPPORTED );
+ rConv.convertAxOrientation( rPropMap, maSize, mnOrientation );
+ rConv.convertScrollBar( rPropMap, mnMin, mnMax, mnPosition, mnSmallChange, mnLargeChange, mbAwtModel );
+ AxControlModelBase::convertProperties( rPropMap, rConv );
+}
+
+// ============================================================================
+
+AxContainerModelBase::AxContainerModelBase() :
+ AxFontDataModel( false ), // no support for Align property
+ maLogicalSize( AX_CONTAINER_DEFWIDTH, AX_CONTAINER_DEFHEIGHT ),
+ maScrollPos( 0, 0 ),
+ mnBackColor( AX_SYSCOLOR_BUTTONFACE ),
+ mnTextColor( AX_SYSCOLOR_BUTTONTEXT ),
+ mnFlags( AX_CONTAINER_DEFFLAGS ),
+ mnBorderColor( AX_SYSCOLOR_BUTTONTEXT ),
+ mnBorderStyle( AX_BORDERSTYLE_NONE ),
+ mnScrollBars( AX_CONTAINER_SCR_NONE ),
+ mnCycleType( AX_CONTAINER_CYCLEALL ),
+ mnSpecialEffect( AX_SPECIALEFFECT_FLAT ),
+ mnPicAlign( AX_PICALIGN_CENTER ),
+ mnPicSizeMode( AX_PICSIZE_CLIP ),
+ mbPicTiling( false )
+{
+ setAwtModelMode();
+ // different default size for frame
+ maSize = AxPairData( AX_CONTAINER_DEFWIDTH, AX_CONTAINER_DEFHEIGHT );
+}
+
+void AxContainerModelBase::importProperty( sal_Int32 nPropId, const OUString& rValue )
+{
+ if( nPropId == XML_Caption )
+ maCaption = rValue;
+}
+
+bool AxContainerModelBase::importBinaryModel( BinaryInputStream& rInStrm )
+{
+ AxBinaryPropertyReader aReader( rInStrm );
+ aReader.skipUndefinedProperty();
+ aReader.readIntProperty< sal_uInt32 >( mnBackColor );
+ aReader.readIntProperty< sal_uInt32 >( mnTextColor );
+ aReader.skipIntProperty< sal_uInt32 >(); // next availbale control ID
+ aReader.skipUndefinedProperty();
+ aReader.skipUndefinedProperty();
+ aReader.readIntProperty< sal_uInt32 >( mnFlags );
+ aReader.readIntProperty< sal_uInt8 >( mnBorderStyle );
+ aReader.skipIntProperty< sal_uInt8 >(); // mouse pointer
+ aReader.readIntProperty< sal_uInt8 >( mnScrollBars );
+ aReader.readPairProperty( maSize );
+ aReader.readPairProperty( maLogicalSize );
+ aReader.readPairProperty( maScrollPos );
+ aReader.skipIntProperty< sal_uInt32 >(); // number of control groups
+ aReader.skipUndefinedProperty();
+ aReader.skipPictureProperty(); // mouse icon
+ aReader.readIntProperty< sal_uInt8 >( mnCycleType );
+ aReader.readIntProperty< sal_uInt8 >( mnSpecialEffect );
+ aReader.readIntProperty< sal_uInt32 >( mnBorderColor );
+ aReader.readStringProperty( maCaption );
+ aReader.readFontProperty( maFontData );
+ aReader.readPictureProperty( maPictureData );
+ aReader.skipIntProperty< sal_Int32 >(); // zoom
+ aReader.readIntProperty< sal_uInt8 >( mnPicAlign );
+ aReader.readBoolProperty( mbPicTiling );
+ aReader.readIntProperty< sal_uInt8 >( mnPicSizeMode );
+ aReader.skipIntProperty< sal_uInt32 >(); // shape cookie
+ aReader.skipIntProperty< sal_uInt32 >(); // draw buffer size
+ return aReader.finalizeImport();
+}
+
+bool AxContainerModelBase::importClassTable( BinaryInputStream& rInStrm, AxClassTable& orClassTable )
+{
+ bool bValid = true;
+ orClassTable.clear();
+ if( !getFlag( mnFlags, AX_CONTAINER_NOCLASSTABLE ) )
+ {
+ sal_uInt16 nCount = rInStrm.readuInt16();
+ for( sal_uInt16 nIndex = 0; bValid && (nIndex < nCount); ++nIndex )
+ {
+ orClassTable.push_back( OUString() );
+ AxBinaryPropertyReader aReader( rInStrm );
+ aReader.readGuidProperty( orClassTable.back() );
+ aReader.skipGuidProperty(); // source interface GUID
+ aReader.skipUndefinedProperty();
+ aReader.skipGuidProperty(); // default interface GUID
+ aReader.skipIntProperty< sal_uInt32 >(); // class table and var flags
+ aReader.skipIntProperty< sal_uInt32 >(); // method count
+ aReader.skipIntProperty< sal_Int32 >(); // IDispatch identifier for linked cell access
+ aReader.skipIntProperty< sal_uInt16 >(); // get function index for linked cell access
+ aReader.skipIntProperty< sal_uInt16 >(); // put function index for linked cell access
+ aReader.skipIntProperty< sal_uInt16 >(); // linked cell access property type
+ aReader.skipIntProperty< sal_uInt16 >(); // get function index of value
+ aReader.skipIntProperty< sal_uInt16 >(); // put function index of value
+ aReader.skipIntProperty< sal_uInt16 >(); // value type
+ aReader.skipIntProperty< sal_Int32 >(); // IDispatch identifier for source range access
+ aReader.skipIntProperty< sal_uInt16 >(); // get function index for source range access
+ bValid = aReader.finalizeImport();
+ }
+ }
+ return bValid;
}
// ============================================================================
-AxControl::AxControl( const OUString& rName ) :
+AxFrameModel::AxFrameModel()
+{
+}
+
+ApiControlType AxFrameModel::getControlType() const
+{
+ return API_CONTROL_GROUPBOX;
+}
+
+void AxFrameModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const
+{
+ rPropMap.setProperty( PROP_Label, maCaption );
+ rPropMap.setProperty( PROP_Enabled, getFlag( mnFlags, AX_CONTAINER_ENABLED ) );
+ AxContainerModelBase::convertProperties( rPropMap, rConv );
+}
+
+// ============================================================================
+
+AxUserFormModel::AxUserFormModel()
+{
+}
+
+ApiControlType AxUserFormModel::getControlType() const
+{
+ return API_CONTROL_DIALOG;
+}
+
+void AxUserFormModel::convertProperties( PropertyMap& rPropMap, const ControlConverter& rConv ) const
+{
+ rPropMap.setProperty( PROP_Title, maCaption );
+ rConv.convertColor( rPropMap, PROP_BackgroundColor, mnBackColor );
+ AxContainerModelBase::convertProperties( rPropMap, rConv );
+}
+
+// ============================================================================
+
+EmbeddedControl::EmbeddedControl( const OUString& rName ) :
maName( rName )
{
}
-AxControl::~AxControl()
+EmbeddedControl::~EmbeddedControl()
{
}
-AxControlModelBase* AxControl::createModel( const OUString& rClassId )
+ControlModelRef EmbeddedControl::createModel( const OUString& rClassId )
{
- // TODO: move into a factory
- maClassId = rClassId.toAsciiUpperCase();
- if( maClassId.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "{D7053240-CE69-11CD-A777-00DD01143C57}" ) ) ) // Forms.CommandButton.1
+ OUString aClassId = rClassId.toAsciiUpperCase();
+ if( aClassId.equalsAscii( AX_GUID_COMMANDBUTTON ) )
mxModel.reset( new AxCommandButtonModel );
- else if( maClassId.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "{978C9E23-D4B0-11CE-BF2D-00AA003F40D0}" ) ) ) // Forms.Label.1
+ else if( aClassId.equalsAscii( AX_GUID_LABEL ) )
mxModel.reset( new AxLabelModel );
- else if( maClassId.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "{4C599241-6926-101B-9992-00000B65C6F9}" ) ) ) // Forms.Image.1
+ else if( aClassId.equalsAscii( AX_GUID_IMAGE ) )
mxModel.reset( new AxImageModel );
- else if( maClassId.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "{8BD21D60-EC42-11CE-9E0D-00AA006002F3}" ) ) ) // Forms.ToggleButton.1
+ else if( aClassId.equalsAscii( AX_GUID_TOGGLEBUTTON ) )
mxModel.reset( new AxToggleButtonModel );
- else if( maClassId.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "{8BD21D40-EC42-11CE-9E0D-00AA006002F3}" ) ) ) // Forms.CheckBox.1
+ else if( aClassId.equalsAscii( AX_GUID_CHECKBOX ) )
mxModel.reset( new AxCheckBoxModel );
- else if( maClassId.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "{8BD21D50-EC42-11CE-9E0D-00AA006002F3}" ) ) ) // Forms.OptionButton.1
+ else if( aClassId.equalsAscii( AX_GUID_OPTIONBUTTON ) )
mxModel.reset( new AxOptionButtonModel );
- else if( maClassId.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "{8BD21D10-EC42-11CE-9E0D-00AA006002F3}" ) ) ) // Forms.TextBox.1
+ else if( aClassId.equalsAscii( AX_GUID_TEXTBOX ) )
mxModel.reset( new AxTextBoxModel );
- else if( maClassId.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "{8BD21D20-EC42-11CE-9E0D-00AA006002F3}" ) ) ) // Forms.ListBox.1
+ else if( aClassId.equalsAscii( AX_GUID_LISTBOX ) )
mxModel.reset( new AxListBoxModel );
- else if( maClassId.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "{8BD21D30-EC42-11CE-9E0D-00AA006002F3}" ) ) ) // Forms.ComboBox.1
+ else if( aClassId.equalsAscii( AX_GUID_COMBOBOX ) )
mxModel.reset( new AxComboBoxModel );
- else if( maClassId.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "{79176FB0-B7F2-11CE-97EF-00AA006D2776}" ) ) ) // Forms.SpinButton.1
+ else if( aClassId.equalsAscii( AX_GUID_SPINBUTTON ) )
mxModel.reset( new AxSpinButtonModel );
- else if( maClassId.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "{DFD181E0-5E2F-11CE-A449-00AA004A803D}" ) ) ) // Forms.ScrollBar.1
+ else if( aClassId.equalsAscii( AX_GUID_SCROLLBAR ) )
mxModel.reset( new AxScrollBarModel );
+ else if( aClassId.equalsAscii( AX_GUID_FRAME ) )
+ mxModel.reset( new AxFrameModel );
+ else if( aClassId.equalsAscii( COMCTL_GUID_SCROLLBAR_60 ) )
+ mxModel.reset( new ComCtlScrollBarModel( 6 ) );
else
mxModel.reset();
- return mxModel.get();
+ // embedded controls are form component instances
+ if( mxModel.get() )
+ mxModel->setFormComponentMode();
+
+ return mxModel;
}
-void AxControl::importBinaryModel( BinaryInputStream& rInStrm )
+OUString EmbeddedControl::getServiceName() const
{
- if( AxControlModelBase* pModel = createModel( OleHelper::importGuid( rInStrm ) ) )
- pModel->importBinaryModel( rInStrm );
+ return mxModel.get() ? mxModel->getServiceName() : OUString();
}
-Reference< XControlModel > AxControl::convertAndInsert( AxControlHelper& rHelper ) const
+bool EmbeddedControl::convertProperties( const Reference< XControlModel >& rxCtrlModel, const ControlConverter& rConv ) const
{
- Reference< XControlModel > xCtrlModel;
- if( mxModel.get() ) try
+ if( mxModel.get() && rxCtrlModel.is() && (maName.getLength() > 0) )
{
- Reference< XIndexContainer > xFormIC( rHelper.getControlForm(), UNO_QUERY_THROW );
+ PropertyMap aPropMap;
+ aPropMap.setProperty( PROP_Name, maName );
+ mxModel->convertProperties( aPropMap, rConv );
+ PropertySet aPropSet( rxCtrlModel );
+ aPropSet.setProperties( aPropMap );
+ return true;
+ }
+ return false;
+}
- // document model creates the form control model
- xCtrlModel.set( rHelper.getFilter().getModelFactory()->createInstance( mxModel->getServiceName() ), UNO_QUERY_THROW );
- Reference< XFormComponent > xFormComp( xCtrlModel, UNO_QUERY_THROW );
+// ============================================================================
+
+EmbeddedForm::EmbeddedForm( const Reference< XMultiServiceFactory >& rxModelFactory,
+ const Reference< XDrawPage >& rxDrawPage, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr ) :
+ ControlConverter( rGraphicHelper, bDefaultColorBgr ),
+ mxModelFactory( rxModelFactory ),
+ mxFormsSupp( rxDrawPage, UNO_QUERY )
+{
+ OSL_ENSURE( mxModelFactory.is(), "EmbeddedForm::EmbeddedForm - missing service factory" );
+}
+
+Reference< XControlModel > EmbeddedForm::convertAndInsert( const EmbeddedControl& rControl )
+{
+ if( mxModelFactory.is() && rControl.hasModel() ) try
+ {
+ // create the UNO control model
+ OUString aServiceName = rControl.getServiceName();
+ Reference< XFormComponent > xFormComp( mxModelFactory->createInstance( aServiceName ), UNO_QUERY_THROW );
+ Reference< XControlModel > xCtrlModel( xFormComp, UNO_QUERY_THROW );
- // insert control model into the passed form
+ // insert the control into the form
+ Reference< XIndexContainer > xFormIC( createForm(), UNO_SET_THROW );
sal_Int32 nNewIndex = xFormIC->getCount();
xFormIC->insertByIndex( nNewIndex, Any( xFormComp ) );
- // convert all control properties
- PropertyMap aPropMap;
- aPropMap.setProperty( PROP_Name, maName );
- mxModel->convertProperties( rHelper, aPropMap );
-
- PropertySet aPropSet( xCtrlModel );
- aPropSet.setProperties( aPropMap );
+ // convert the control properties
+ if( rControl.convertProperties( xCtrlModel, *this ) )
+ return xCtrlModel;
}
catch( Exception& )
{
- xCtrlModel.clear(); // on error: forget the created form control model
}
- return xCtrlModel;
+ return Reference< XControlModel >();
+}
+
+Reference< XIndexContainer > EmbeddedForm::createForm()
+{
+ if( mxFormsSupp.is() )
+ {
+ try
+ {
+ Reference< XNameContainer > xFormsNC( mxFormsSupp->getForms(), UNO_SET_THROW );
+ OUString aFormName = CREATE_OUSTRING( "Standard" );
+ if( xFormsNC->hasByName( aFormName ) )
+ {
+ mxFormIC.set( xFormsNC->getByName( aFormName ), UNO_QUERY_THROW );
+ }
+ else if( mxModelFactory.is() )
+ {
+ Reference< XForm > xForm( mxModelFactory->createInstance( CREATE_OUSTRING( "com.sun.star.form.component.Form" ) ), UNO_QUERY_THROW );
+ xFormsNC->insertByName( aFormName, Any( xForm ) );
+ mxFormIC.set( xForm, UNO_QUERY_THROW );
+ }
+ }
+ catch( Exception& )
+ {
+ }
+ // always clear the forms supplier to not try to create the form again
+ mxFormsSupp.clear();
+ }
+ return mxFormIC;
}
// ============================================================================
} // namespace ole
} // namespace oox
-
diff --git a/oox/source/ole/axcontrolfragment.cxx b/oox/source/ole/axcontrolfragment.cxx
index e641ec40d71b..ecd782da2cb0 100644
--- a/oox/source/ole/axcontrolfragment.cxx
+++ b/oox/source/ole/axcontrolfragment.cxx
@@ -30,8 +30,12 @@
#include "oox/helper/binaryoutputstream.hxx"
#include "oox/core/xmlfilterbase.hxx"
#include "oox/ole/axcontrol.hxx"
+#include "oox/ole/olehelper.hxx"
+#include "oox/ole/olestorage.hxx"
using ::rtl::OUString;
+using ::com::sun::star::io::XInputStream;
+using ::com::sun::star::uno::Reference;
using ::oox::core::ContextHandler2;
using ::oox::core::ContextHandlerRef;
using ::oox::core::FragmentHandler2;
@@ -42,7 +46,7 @@ namespace ole {
// ============================================================================
-AxControlPropertyContext::AxControlPropertyContext( FragmentHandler2& rFragment, AxControlModelBase& rModel ) :
+AxControlPropertyContext::AxControlPropertyContext( FragmentHandler2& rFragment, ControlModelBase& rModel ) :
ContextHandler2( rFragment ),
mrModel( rModel ),
mnPropId( XML_TOKEN_INVALID )
@@ -87,7 +91,7 @@ ContextHandlerRef AxControlPropertyContext::onCreateContext( sal_Int32 nElement,
// ============================================================================
-AxControlFragment::AxControlFragment( XmlFilterBase& rFilter, const OUString& rFragmentPath, AxControl& rControl ) :
+AxControlFragment::AxControlFragment( XmlFilterBase& rFilter, const OUString& rFragmentPath, EmbeddedControl& rControl ) :
FragmentHandler2( rFilter, rFragmentPath, true ),
mrControl( rControl )
{
@@ -101,7 +105,7 @@ ContextHandlerRef AxControlFragment::onCreateContext( sal_Int32 nElement, const
switch( rAttribs.getToken( AX_TOKEN( persistence ), XML_TOKEN_INVALID ) )
{
case XML_persistPropertyBag:
- if( AxControlModelBase* pModel = mrControl.createModel( aClassId ) )
+ if( ControlModelBase* pModel = mrControl.createModel( aClassId ).get() )
return new AxControlPropertyContext( *this, *pModel );
break;
@@ -113,10 +117,30 @@ ContextHandlerRef AxControlFragment::onCreateContext( sal_Int32 nElement, const
BinaryXInputStream aInStrm( getFilter().openInputStream( aFragmentPath ), true );
if( !aInStrm.isEof() )
{
- mrControl.importBinaryModel( aInStrm );
// binary stream contains a copy of the class ID, must be equal to attribute value
- OSL_ENSURE( !mrControl.getModel() || aClassId.equalsIgnoreAsciiCase( mrControl.getClassId() ),
+ OUString aStrmClassId = OleHelper::importGuid( aInStrm );
+ OSL_ENSURE( aClassId.equalsIgnoreAsciiCase( aStrmClassId ),
"AxControlFragment::importBinaryControl - form control class ID mismatch" );
+ if( ControlModelBase* pModel = mrControl.createModel( aStrmClassId ).get() )
+ pModel->importBinaryModel( aInStrm );
+ }
+ }
+ }
+ break;
+
+ case XML_persistStorage:
+ {
+ OUString aFragmentPath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
+ if( aFragmentPath.getLength() > 0 )
+ {
+ Reference< XInputStream > xStrgStrm = getFilter().openInputStream( aFragmentPath );
+ if( xStrgStrm.is() )
+ {
+ OleStorage aStorage( getFilter().getGlobalFactory(), xStrgStrm, false );
+ BinaryXInputStream aInStrm( aStorage.openInputStream( CREATE_OUSTRING( "f" ) ), true );
+ if( !aInStrm.isEof() )
+ if( AxContainerModelBase* pModel = dynamic_cast< AxContainerModelBase* >( mrControl.createModel( aClassId ).get() ) )
+ pModel->importBinaryModel( aInStrm );
}
}
}
@@ -130,4 +154,3 @@ ContextHandlerRef AxControlFragment::onCreateContext( sal_Int32 nElement, const
} // namespace ole
} // namespace oox
-
diff --git a/oox/source/ole/axcontrolhelper.cxx b/oox/source/ole/axcontrolhelper.cxx
deleted file mode 100644
index 1ffb4343aaf5..000000000000
--- a/oox/source/ole/axcontrolhelper.cxx
+++ /dev/null
@@ -1,175 +0,0 @@
-/*************************************************************************
- *
- * 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
- * <http://www.openoffice.org/license.html>
- * for a copy of the LGPLv3 License.
- *
- ************************************************************************/
-
-#include "oox/ole/axcontrolhelper.hxx"
-#include <com/sun/star/container/XNameContainer.hpp>
-#include <com/sun/star/form/XForm.hpp>
-#include <com/sun/star/form/XFormsSupplier.hpp>
-#include "tokens.hxx"
-#include "oox/helper/containerhelper.hxx"
-#include "oox/core/filterbase.hxx"
-#include "oox/drawingml/color.hxx"
-
-using ::rtl::OUString;
-using ::com::sun::star::uno::Any;
-using ::com::sun::star::uno::Exception;
-using ::com::sun::star::uno::Reference;
-using ::com::sun::star::uno::UNO_QUERY_THROW;
-using ::com::sun::star::uno::UNO_SET_THROW;
-using ::com::sun::star::container::XNameContainer;
-using ::com::sun::star::graphic::XGraphic;
-using ::com::sun::star::drawing::XDrawPage;
-using ::com::sun::star::form::XForm;
-using ::com::sun::star::form::XFormsSupplier;
-using ::oox::core::FilterBase;
-
-namespace oox {
-namespace ole {
-
-// ============================================================================
-
-namespace {
-
-const sal_uInt32 AX_COLORTYPE_MASK = 0xFF000000;
-const sal_uInt32 AX_COLORTYPE_CLIENT = 0x00000000;
-const sal_uInt32 AX_COLORTYPE_PALETTE = 0x01000000;
-const sal_uInt32 AX_COLORTYPE_BGR = 0x02000000;
-const sal_uInt32 AX_COLORTYPE_SYSCOLOR = 0x80000000;
-
-const sal_uInt32 AX_PALETTECOLOR_MASK = 0x0000FFFF;
-const sal_uInt32 AX_BGRCOLOR_MASK = 0x00FFFFFF;
-const sal_uInt32 AX_SYSTEMCOLOR_MASK = 0x0000FFFF;
-
-// ----------------------------------------------------------------------------
-
-/** Returns the UNO RGB color from the passed encoded OLE BGR color. */
-inline sal_Int32 lclDecodeBgrColor( sal_uInt32 nAxColor )
-{
- return static_cast< sal_Int32 >( ((nAxColor & 0x0000FF) << 16) | (nAxColor & 0x00FF00) | ((nAxColor & 0xFF0000) >> 16) );
-}
-
-} // namespace
-
-// ============================================================================
-
-AxControlHelper::AxControlHelper( const FilterBase& rFilter, AxDefaultColorMode eColorMode ) :
- mrFilter( rFilter ),
- meColorMode( eColorMode ),
- mbHasFormQuerried( false )
-{
-}
-
-AxControlHelper::~AxControlHelper()
-{
-}
-
-Reference< XForm > AxControlHelper::getControlForm() const
-{
- if( !mbHasFormQuerried )
- {
- mbHasFormQuerried = true;
- mxForm = createControlForm(); // virtual call
- }
- return mxForm;
-}
-
-sal_Int32 AxControlHelper::convertColor( sal_uInt32 nAxColor ) const
-{
- static const sal_Int32 spnSystemColors[] =
- {
- XML_scrollBar, XML_background, XML_activeCaption, XML_inactiveCaption,
- XML_menu, XML_window, XML_windowFrame, XML_menuText,
- XML_windowText, XML_captionText, XML_activeBorder, XML_inactiveBorder,
- XML_appWorkspace, XML_highlight, XML_highlightText, XML_btnFace,
- XML_btnShadow, XML_grayText, XML_btnText, XML_inactiveCaptionText,
- XML_btnHighlight, XML_3dDkShadow, XML_3dLight, XML_infoText,
- XML_infoBk
- };
-
- switch( nAxColor & AX_COLORTYPE_MASK )
- {
- case AX_COLORTYPE_CLIENT:
- switch( meColorMode )
- {
- case AX_DEFAULTCOLORMODE_BGR: return lclDecodeBgrColor( nAxColor );
- case AX_DEFAULTCOLORMODE_PALETTE: return mrFilter.getPaletteColor( nAxColor & AX_PALETTECOLOR_MASK );
- }
- break;
-
- case AX_COLORTYPE_PALETTE:
- return mrFilter.getPaletteColor( nAxColor & AX_PALETTECOLOR_MASK );
-
- case AX_COLORTYPE_BGR:
- return lclDecodeBgrColor( nAxColor );
-
- case AX_COLORTYPE_SYSCOLOR:
- return mrFilter.getSystemColor( STATIC_ARRAY_SELECT( spnSystemColors, nAxColor & AX_SYSTEMCOLOR_MASK, XML_TOKEN_INVALID ), API_RGB_WHITE );
- }
- OSL_ENSURE( false, "AxControlHelper::convertColor - unknown color type" );
- return 0;
-}
-
-// ============================================================================
-
-AxEmbeddedControlHelper::AxEmbeddedControlHelper( const FilterBase& rFilter,
- const Reference< XDrawPage >& rxDrawPage, AxDefaultColorMode eColorMode ) :
- AxControlHelper( rFilter, eColorMode ),
- mxDrawPage( rxDrawPage )
-{
-}
-
-Reference< XForm > AxEmbeddedControlHelper::createControlForm() const
-{
- Reference< XForm > xForm;
- try
- {
- Reference< XFormsSupplier > xFormsSupplier( mxDrawPage, UNO_QUERY_THROW );
- Reference< XNameContainer > xFormsNC( xFormsSupplier->getForms(), UNO_SET_THROW );
- OUString aFormName = CREATE_OUSTRING( "Standard" );
- if( xFormsNC->hasByName( aFormName ) )
- {
- xFormsNC->getByName( aFormName ) >>= xForm;
- }
- else
- {
- Reference< XForm > xNewForm( getFilter().getModelFactory()->createInstance( CREATE_OUSTRING( "com.sun.star.form.component.Form" ) ), UNO_QUERY_THROW );
- xFormsNC->insertByName( aFormName, Any( xNewForm ) );
- // return the form if insertion did not fail
- xForm = xNewForm;
- }
- }
- catch( Exception& )
- {
- }
- return xForm;
-}
-
-// ============================================================================
-
-} // namespace ole
-} // namespace oox
-
diff --git a/oox/source/ole/makefile.mk b/oox/source/ole/makefile.mk
index 5fe0c08dbd6f..4e01392d4a57 100644
--- a/oox/source/ole/makefile.mk
+++ b/oox/source/ole/makefile.mk
@@ -44,10 +44,14 @@ SLOFILES = \
$(SLO)$/axbinaryreader.obj \
$(SLO)$/axcontrol.obj \
$(SLO)$/axcontrolfragment.obj \
- $(SLO)$/axcontrolhelper.obj \
$(SLO)$/olehelper.obj \
$(SLO)$/oleobjecthelper.obj \
- $(SLO)$/vbainputstream.obj
+ $(SLO)$/olestorage.obj \
+ $(SLO)$/vbacontrol.obj \
+ $(SLO)$/vbahelper.obj \
+ $(SLO)$/vbainputstream.obj \
+ $(SLO)$/vbamodule.obj \
+ $(SLO)$/vbaproject.obj
# --- Targets -------------------------------------------------------
diff --git a/oox/source/ole/olehelper.cxx b/oox/source/ole/olehelper.cxx
index f26fb9d0cec3..0a0796e15a7e 100644
--- a/oox/source/ole/olehelper.cxx
+++ b/oox/source/ole/olehelper.cxx
@@ -27,7 +27,9 @@
#include "oox/ole/olehelper.hxx"
#include <rtl/ustrbuf.hxx>
+#include "tokens.hxx"
#include "oox/helper/binaryinputstream.hxx"
+#include "oox/helper/graphichelper.hxx"
using ::rtl::OUString;
using ::rtl::OUStringBuffer;
@@ -39,9 +41,24 @@ namespace ole {
namespace {
-const sal_Char* const OLE_GUID_STDFONT = "{0BE35203-8F91-11CE-9DE3-00AA004BB851}";
-const sal_Char* const OLE_GUID_STDPIC = "{0BE35204-8F91-11CE-9DE3-00AA004BB851}";
-const sal_Char* const OLE_GUID_STDHLINK = "{79EAC9D0-BAF9-11CE-8C82-00AA004BA90B}";
+const sal_uInt32 OLE_COLORTYPE_MASK = 0xFF000000;
+const sal_uInt32 OLE_COLORTYPE_CLIENT = 0x00000000;
+const sal_uInt32 OLE_COLORTYPE_PALETTE = 0x01000000;
+const sal_uInt32 OLE_COLORTYPE_BGR = 0x02000000;
+const sal_uInt32 OLE_COLORTYPE_SYSCOLOR = 0x80000000;
+
+const sal_uInt32 OLE_PALETTECOLOR_MASK = 0x0000FFFF;
+const sal_uInt32 OLE_BGRCOLOR_MASK = 0x00FFFFFF;
+const sal_uInt32 OLE_SYSTEMCOLOR_MASK = 0x0000FFFF;
+
+/** Returns the UNO RGB color from the passed encoded OLE BGR color. */
+inline sal_Int32 lclDecodeBgrColor( sal_uInt32 nOleColor )
+{
+ return static_cast< sal_Int32 >( ((nOleColor & 0x0000FF) << 16) | (nOleColor & 0x00FF00) | ((nOleColor & 0xFF0000) >> 16) );
+}
+
+// ----------------------------------------------------------------------------
+
const sal_Char* const OLE_GUID_URLMONIKER = "{79EAC9E0-BAF9-11CE-8C82-00AA004BA90B}";
const sal_Char* const OLE_GUID_FILEMONIKER = "{00000303-0000-0000-C000-000000000046}";
@@ -69,14 +86,15 @@ void lclAppendHex( OUStringBuffer& orBuffer, Type nValue )
orBuffer.setCharAt( nCharIdx, spcHexChars[ nValue & 0xF ] );
}
-OUString lclReadStdHlinkString( BinaryInputStream& rInStrm, rtl_TextEncoding eTextEnc, bool bUnicode )
+OUString lclReadStdHlinkString( BinaryInputStream& rInStrm, bool bUnicode )
{
OUString aRet;
sal_Int32 nChars = rInStrm.readInt32();
if( nChars > 0 )
{
sal_Int32 nReadChars = getLimitedValue< sal_Int32, sal_Int32 >( nChars, 0, SAL_MAX_UINT16 );
- aRet = bUnicode ? rInStrm.readUnicodeArray( nReadChars, true ) : rInStrm.readCharArrayUC( nReadChars, eTextEnc, true );
+ // byte strings are always in ANSI (Windows 1252) encoding
+ aRet = bUnicode ? rInStrm.readUnicodeArray( nReadChars, true ) : rInStrm.readCharArrayUC( nReadChars, RTL_TEXTENCODING_MS_1252, true );
// strings are NUL terminated, remove trailing NUL and possible other garbage
sal_Int32 nNulPos = aRet.indexOf( '\0' );
if( nNulPos >= 0 )
@@ -91,6 +109,58 @@ OUString lclReadStdHlinkString( BinaryInputStream& rInStrm, rtl_TextEncoding eTe
// ============================================================================
+StdFontInfo::StdFontInfo() :
+ mnHeight( 0 ),
+ mnWeight( OLE_STDFONT_NORMAL ),
+ mnCharSet( WINDOWS_CHARSET_ANSI ),
+ mnFlags( 0 )
+{
+}
+
+StdFontInfo::StdFontInfo( const ::rtl::OUString& rName, sal_uInt32 nHeight,
+ sal_uInt16 nWeight, sal_uInt16 nCharSet, sal_uInt8 nFlags ) :
+ maName( rName ),
+ mnHeight( nHeight ),
+ mnWeight( nWeight ),
+ mnCharSet( nCharSet ),
+ mnFlags( nFlags )
+{
+}
+
+// ============================================================================
+
+/*static*/ sal_Int32 OleHelper::decodeOleColor(
+ const GraphicHelper& rGraphicHelper, sal_uInt32 nOleColor, bool bDefaultColorBgr )
+{
+ static const sal_Int32 spnSystemColors[] =
+ {
+ XML_scrollBar, XML_background, XML_activeCaption, XML_inactiveCaption,
+ XML_menu, XML_window, XML_windowFrame, XML_menuText,
+ XML_windowText, XML_captionText, XML_activeBorder, XML_inactiveBorder,
+ XML_appWorkspace, XML_highlight, XML_highlightText, XML_btnFace,
+ XML_btnShadow, XML_grayText, XML_btnText, XML_inactiveCaptionText,
+ XML_btnHighlight, XML_3dDkShadow, XML_3dLight, XML_infoText,
+ XML_infoBk
+ };
+
+ switch( nOleColor & OLE_COLORTYPE_MASK )
+ {
+ case OLE_COLORTYPE_CLIENT:
+ return bDefaultColorBgr ? lclDecodeBgrColor( nOleColor ) : rGraphicHelper.getPaletteColor( nOleColor & OLE_PALETTECOLOR_MASK );
+
+ case OLE_COLORTYPE_PALETTE:
+ return rGraphicHelper.getPaletteColor( nOleColor & OLE_PALETTECOLOR_MASK );
+
+ case OLE_COLORTYPE_BGR:
+ return lclDecodeBgrColor( nOleColor );
+
+ case OLE_COLORTYPE_SYSCOLOR:
+ return rGraphicHelper.getSystemColor( STATIC_ARRAY_SELECT( spnSystemColors, nOleColor & OLE_SYSTEMCOLOR_MASK, XML_TOKEN_INVALID ), API_RGB_WHITE );
+ }
+ OSL_ENSURE( false, "OleHelper::decodeOleColor - unknown color type" );
+ return API_RGB_BLACK;
+}
+
/*static*/ OUString OleHelper::importGuid( BinaryInputStream& rInStrm )
{
OUStringBuffer aBuffer;
@@ -110,6 +180,24 @@ OUString lclReadStdHlinkString( BinaryInputStream& rInStrm, rtl_TextEncoding eTe
return aBuffer.makeStringAndClear();
}
+/*static*/ bool OleHelper::importStdFont( StdFontInfo& orFontInfo, BinaryInputStream& rInStrm, bool bWithGuid )
+{
+ if( bWithGuid )
+ {
+ bool bIsStdFont = importGuid( rInStrm ).equalsAscii( OLE_GUID_STDFONT );
+ OSL_ENSURE( bIsStdFont, "OleHelper::importStdFont - unexpected header GUID, expected StdFont" );
+ if( !bIsStdFont )
+ return false;
+ }
+
+ sal_uInt8 nVersion, nNameLen;
+ rInStrm >> nVersion >> orFontInfo.mnCharSet >> orFontInfo.mnFlags >> orFontInfo.mnWeight >> orFontInfo.mnHeight >> nNameLen;
+ // according to spec the name is ASCII
+ orFontInfo.maName = rInStrm.readCharArrayUC( nNameLen, RTL_TEXTENCODING_ASCII_US );
+ OSL_ENSURE( nVersion <= 1, "OleHelper::importStdFont - wrong version" );
+ return !rInStrm.isEof() && (nVersion <= 1);
+}
+
/*static*/ bool OleHelper::importStdPic( StreamDataSequence& orGraphicData, BinaryInputStream& rInStrm, bool bWithGuid )
{
if( bWithGuid )
@@ -127,7 +215,7 @@ OUString lclReadStdHlinkString( BinaryInputStream& rInStrm, rtl_TextEncoding eTe
return !rInStrm.isEof() && (nStdPicId == OLE_STDPIC_ID) && (nBytes > 0) && (rInStrm.readData( orGraphicData, nBytes ) == nBytes);
}
-/*static*/ bool OleHelper::importStdHlink( StdHlinkInfo& orHlinkInfo, BinaryInputStream& rInStrm, rtl_TextEncoding eTextEnc, bool bWithGuid )
+/*static*/ bool OleHelper::importStdHlink( StdHlinkInfo& orHlinkInfo, BinaryInputStream& rInStrm, bool bWithGuid )
{
if( bWithGuid )
{
@@ -145,10 +233,10 @@ OUString lclReadStdHlinkString( BinaryInputStream& rInStrm, rtl_TextEncoding eTe
// display string
if( getFlag( nFlags, OLE_STDHLINK_HASDISPLAY ) )
- orHlinkInfo.maDisplay = lclReadStdHlinkString( rInStrm, eTextEnc, true );
+ orHlinkInfo.maDisplay = lclReadStdHlinkString( rInStrm, true );
// frame string
if( getFlag( nFlags, OLE_STDHLINK_HASFRAME ) )
- orHlinkInfo.maFrame = lclReadStdHlinkString( rInStrm, eTextEnc, true );
+ orHlinkInfo.maFrame = lclReadStdHlinkString( rInStrm, true );
// target
if( getFlag( nFlags, OLE_STDHLINK_HASTARGET ) )
@@ -156,7 +244,7 @@ OUString lclReadStdHlinkString( BinaryInputStream& rInStrm, rtl_TextEncoding eTe
if( getFlag( nFlags, OLE_STDHLINK_ASSTRING ) )
{
OSL_ENSURE( getFlag( nFlags, OLE_STDHLINK_ABSOLUTE ), "OleHelper::importStdHlink - link not absolute" );
- orHlinkInfo.maTarget = lclReadStdHlinkString( rInStrm, eTextEnc, true );
+ orHlinkInfo.maTarget = lclReadStdHlinkString( rInStrm, true );
}
else // hyperlink moniker
{
@@ -167,7 +255,7 @@ OUString lclReadStdHlinkString( BinaryInputStream& rInStrm, rtl_TextEncoding eTe
sal_Int16 nUpLevels;
rInStrm >> nUpLevels;
OSL_ENSURE( (nUpLevels == 0) || !getFlag( nFlags, OLE_STDHLINK_ABSOLUTE ), "OleHelper::importStdHlink - absolute filename with upcount" );
- orHlinkInfo.maTarget = lclReadStdHlinkString( rInStrm, eTextEnc, false );
+ orHlinkInfo.maTarget = lclReadStdHlinkString( rInStrm, false );
rInStrm.skip( 24 );
sal_Int32 nBytes = rInStrm.readInt32();
if( nBytes > 0 )
@@ -200,9 +288,9 @@ OUString lclReadStdHlinkString( BinaryInputStream& rInStrm, rtl_TextEncoding eTe
// target location
if( getFlag( nFlags, OLE_STDHLINK_HASLOCATION ) )
- orHlinkInfo.maLocation = lclReadStdHlinkString( rInStrm, eTextEnc, true );
+ orHlinkInfo.maLocation = lclReadStdHlinkString( rInStrm, true );
- return true;
+ return !rInStrm.isEof();
}
// ============================================================================
diff --git a/oox/source/ole/olestorage.cxx b/oox/source/ole/olestorage.cxx
new file mode 100755
index 000000000000..0ca2992d47ad
--- /dev/null
+++ b/oox/source/ole/olestorage.cxx
@@ -0,0 +1,423 @@
+/*************************************************************************
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "oox/ole/olestorage.hxx"
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/io/XStream.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <cppuhelper/implbase2.hxx>
+#include "oox/helper/helper.hxx"
+#include "oox/helper/binaryinputstream.hxx"
+#include "oox/helper/binaryoutputstream.hxx"
+
+using ::rtl::OUString;
+using ::com::sun::star::container::XNameContainer;
+using ::com::sun::star::beans::PropertyValue;
+using ::com::sun::star::embed::XStorage;
+using ::com::sun::star::embed::XTransactedObject;
+using ::com::sun::star::io::BufferSizeExceededException;
+using ::com::sun::star::io::IOException;
+using ::com::sun::star::io::NotConnectedException;
+using ::com::sun::star::io::XInputStream;
+using ::com::sun::star::io::XOutputStream;
+using ::com::sun::star::io::XSeekable;
+using ::com::sun::star::io::XStream;
+using ::com::sun::star::lang::IllegalArgumentException;
+using ::com::sun::star::lang::XMultiServiceFactory;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Exception;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::RuntimeException;
+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;
+
+namespace oox {
+namespace ole {
+
+// ============================================================================
+
+namespace {
+
+typedef ::cppu::WeakImplHelper2< XSeekable, XOutputStream > OleOutputStreamBase;
+
+/** Implementation of an OLE storage output stream that inserts itself into the
+ storage when it is closed.
+ */
+class OleOutputStream : public OleOutputStreamBase
+{
+public:
+ explicit OleOutputStream(
+ const Reference< XMultiServiceFactory >& rxFactory,
+ const Reference< XNameContainer >& rxStorage,
+ const OUString& rElementName );
+ virtual ~OleOutputStream();
+
+ virtual void SAL_CALL seek( sal_Int64 nPos ) throw( IllegalArgumentException, IOException, RuntimeException );
+ virtual sal_Int64 SAL_CALL getPosition() throw( IOException, RuntimeException );
+ virtual sal_Int64 SAL_CALL getLength() throw( IOException, RuntimeException );
+
+ virtual void SAL_CALL writeBytes( const Sequence< sal_Int8 >& rData ) throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
+ virtual void SAL_CALL flush() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
+ virtual void SAL_CALL closeOutput() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
+
+private:
+ void ensureSeekable() const throw( IOException );
+ void ensureConnected() const throw( NotConnectedException );
+
+private:
+ Reference< XNameContainer > mxStorage;
+ Reference< XStream > mxTempFile;
+ Reference< XOutputStream > mxOutStrm;
+ Reference< XSeekable > mxSeekable;
+ OUString maElementName;
+};
+
+// ----------------------------------------------------------------------------
+
+OleOutputStream::OleOutputStream( const Reference< XMultiServiceFactory >& rxFactory,
+ const Reference< XNameContainer >& rxStorage, const OUString& rElementName ) :
+ mxStorage( rxStorage ),
+ maElementName( rElementName )
+{
+ try
+ {
+ mxTempFile.set( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TempFile" ) ), UNO_QUERY_THROW );
+ mxOutStrm = mxTempFile->getOutputStream();
+ mxSeekable.set( mxOutStrm, UNO_QUERY );
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+OleOutputStream::~OleOutputStream()
+{
+}
+
+void SAL_CALL OleOutputStream::seek( sal_Int64 nPos ) throw( IllegalArgumentException, IOException, RuntimeException )
+{
+ ensureSeekable();
+ mxSeekable->seek( nPos );
+}
+
+sal_Int64 SAL_CALL OleOutputStream::getPosition() throw( IOException, RuntimeException )
+{
+ ensureSeekable();
+ return mxSeekable->getPosition();
+}
+
+sal_Int64 SAL_CALL OleOutputStream::getLength() throw( IOException, RuntimeException )
+{
+ ensureSeekable();
+ return mxSeekable->getLength();
+}
+
+void SAL_CALL OleOutputStream::writeBytes( const Sequence< sal_Int8 >& rData ) throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
+{
+ ensureConnected();
+ mxOutStrm->writeBytes( rData );
+}
+
+void SAL_CALL OleOutputStream::flush() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
+{
+ ensureConnected();
+ mxOutStrm->flush();
+}
+
+void SAL_CALL OleOutputStream::closeOutput() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
+{
+ ensureConnected();
+ ensureSeekable();
+ // remember the class members
+ Reference< XOutputStream > xOutStrm = mxOutStrm;
+ Reference< XSeekable > xSeekable = mxSeekable;
+ // reset all class members
+ mxOutStrm.clear();
+ mxSeekable.clear();
+ // close stream (and let it throw something if needed)
+ xOutStrm->closeOutput();
+ // on success, insert the stream into the OLE storage (must be seeked back before)
+ xSeekable->seek( 0 );
+ if( !ContainerHelper::insertByName( mxStorage, maElementName, Any( mxTempFile ) ) )
+ throw IOException();
+}
+
+void OleOutputStream::ensureSeekable() const throw( IOException )
+{
+ if( !mxSeekable.is() )
+ throw IOException();
+}
+
+void OleOutputStream::ensureConnected() const throw( NotConnectedException )
+{
+ if( !mxOutStrm.is() )
+ throw NotConnectedException();
+}
+
+} // namespace
+
+// ============================================================================
+
+OleStorage::OleStorage(
+ const Reference< XMultiServiceFactory >& rxFactory,
+ const Reference< XInputStream >& rxInStream,
+ bool bBaseStreamAccess ) :
+ StorageBase( rxInStream, bBaseStreamAccess ),
+ mxFactory( rxFactory ),
+ mpParentStorage( 0 )
+{
+ OSL_ENSURE( mxFactory.is(), "OleStorage::OleStorage - missing service factory" );
+ initStorage( rxInStream );
+}
+
+OleStorage::OleStorage(
+ const Reference< XMultiServiceFactory >& rxFactory,
+ const Reference< XStream >& rxOutStream,
+ bool bBaseStreamAccess ) :
+ StorageBase( rxOutStream, bBaseStreamAccess ),
+ mxFactory( rxFactory ),
+ mpParentStorage( 0 )
+{
+ OSL_ENSURE( mxFactory.is(), "OleStorage::OleStorage - missing service factory" );
+ initStorage( rxOutStream );
+}
+
+OleStorage::OleStorage(
+ const OleStorage& rParentStorage,
+ const Reference< XNameContainer >& rxStorage,
+ const OUString& rElementName,
+ bool bReadOnly ) :
+ StorageBase( rParentStorage, rElementName, bReadOnly ),
+ mxFactory( rParentStorage.mxFactory ),
+ mxStorage( rxStorage ),
+ mpParentStorage( &rParentStorage )
+{
+ OSL_ENSURE( mxStorage.is(), "OleStorage::OleStorage - missing substorage elements" );
+}
+
+OleStorage::OleStorage(
+ const OleStorage& rParentStorage,
+ const Reference< XStream >& rxOutStream,
+ const OUString& rElementName ) :
+ StorageBase( rParentStorage, rElementName, false ),
+ mxFactory( rParentStorage.mxFactory ),
+ mpParentStorage( &rParentStorage )
+{
+ initStorage( rxOutStream );
+}
+
+OleStorage::~OleStorage()
+{
+}
+
+// ----------------------------------------------------------------------------
+
+void OleStorage::initStorage( const Reference< XInputStream >& rxInStream )
+{
+ // if stream is not seekable, create temporary copy
+ Reference< XInputStream > xInStrm = rxInStream;
+ if( !Reference< XSeekable >( xInStrm, UNO_QUERY ).is() ) try
+ {
+ Reference< XStream > xTempFile( mxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TempFile" ) ), UNO_QUERY_THROW );
+ {
+ Reference< XOutputStream > xOutStrm( xTempFile->getOutputStream(), UNO_SET_THROW );
+ /* Pass false to both binary stream objects to keep the UNO
+ streams alive. Life time of these streams is controlled by the
+ tempfile implementation. */
+ BinaryXOutputStream aOutStrm( xOutStrm, false );
+ BinaryXInputStream aInStrm( xInStrm, false );
+ aInStrm.copyToStream( aOutStrm );
+ } // scope closes output stream of tempfile
+ xInStrm = xTempFile->getInputStream();
+ }
+ catch( Exception& )
+ {
+ OSL_ENSURE( false, "OleStorage::initStorage - cannot create temporary copy of input stream" );
+ }
+
+ // create base storage object
+ if( xInStrm.is() ) try
+ {
+ Sequence< Any > aArgs( 2 );
+ aArgs[ 0 ] <<= xInStrm;
+ aArgs[ 1 ] <<= true; // true = do not create a copy of the input stream
+ mxStorage.set( mxFactory->createInstanceWithArguments(
+ CREATE_OUSTRING( "com.sun.star.embed.OLESimpleStorage" ), aArgs ), UNO_QUERY_THROW );
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+void OleStorage::initStorage( const Reference< XStream >& rxOutStream )
+{
+ // create base storage object
+ if( rxOutStream.is() ) try
+ {
+ Sequence< Any > aArgs( 2 );
+ aArgs[ 0 ] <<= rxOutStream;
+ aArgs[ 1 ] <<= true; // true = do not create a copy of the stream
+ mxStorage.set( mxFactory->createInstanceWithArguments(
+ CREATE_OUSTRING( "com.sun.star.embed.OLESimpleStorage" ), aArgs ), UNO_QUERY_THROW );
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+// StorageBase interface ------------------------------------------------------
+
+bool OleStorage::implIsStorage() const
+{
+ if( mxStorage.is() ) try
+ {
+ /* If this is not an OLE storage, hasElements() of the OLESimpleStorage
+ implementation throws an exception. But we do not return the result
+ of hasElements(), because an empty storage is a valid storage too. */
+ mxStorage->hasElements();
+ return true;
+ }
+ catch( Exception& )
+ {
+ }
+ return false;
+}
+
+Reference< XStorage > OleStorage::implGetXStorage() const
+{
+ OSL_ENSURE( false, "OleStorage::getXStorage - not implemented" );
+ return Reference< XStorage >();
+}
+
+void OleStorage::implGetElementNames( ::std::vector< OUString >& orElementNames ) const
+{
+ Sequence< OUString > aNames;
+ if( mxStorage.is() ) try
+ {
+ aNames = mxStorage->getElementNames();
+ if( aNames.getLength() > 0 )
+ orElementNames.insert( orElementNames.end(), aNames.getConstArray(), aNames.getConstArray() + aNames.getLength() );
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+StorageRef OleStorage::implOpenSubStorage( const OUString& rElementName, bool bCreateMissing )
+{
+ StorageRef xSubStorage;
+ if( mxStorage.is() && (rElementName.getLength() > 0) )
+ {
+ try
+ {
+ Reference< XNameContainer > xSubElements( mxStorage->getByName( rElementName ), UNO_QUERY_THROW );
+ xSubStorage.reset( new OleStorage( *this, xSubElements, rElementName, true ) );
+ }
+ catch( Exception& )
+ {
+ }
+
+ /* The OLESimpleStorage API implementation seems to be buggy in the
+ area of writable inplace substorage (sometimes it overwrites other
+ unrelated streams with zero bytes). We go the save way and create a
+ new OLE storage based on a temporary file. All operations are
+ performed on this clean storage. On committing, the storage will be
+ completely re-inserted into the parent storage. */
+ if( !isReadOnly() && (bCreateMissing || xSubStorage.get()) ) try
+ {
+ // create new storage based on a temp file
+ Reference< XStream > xTempFile( mxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TempFile" ) ), UNO_QUERY_THROW );
+ StorageRef xTempStorage( new OleStorage( *this, xTempFile, rElementName ) );
+ // copy existing substorage into temp storage
+ if( xSubStorage.get() )
+ xSubStorage->copyStorageToStorage( *xTempStorage );
+ // return the temp storage to caller
+ xSubStorage = xTempStorage;
+ }
+ catch( Exception& )
+ {
+ }
+ }
+ return xSubStorage;
+}
+
+Reference< XInputStream > OleStorage::implOpenInputStream( const OUString& rElementName )
+{
+ Reference< XInputStream > xInStream;
+ if( mxStorage.is() ) try
+ {
+ xInStream.set( mxStorage->getByName( rElementName ), UNO_QUERY );
+ }
+ catch( Exception& )
+ {
+ }
+ return xInStream;
+}
+
+Reference< XOutputStream > OleStorage::implOpenOutputStream( const OUString& rElementName )
+{
+ Reference< XOutputStream > xOutStream;
+ if( mxStorage.is() && (rElementName.getLength() > 0) )
+ xOutStream.set( new OleOutputStream( mxFactory, mxStorage, rElementName ) );
+ return xOutStream;
+}
+
+void OleStorage::implCommit() const
+{
+ try
+ {
+ // commit this storage (finalizes the file this storage is based on)
+ Reference< XTransactedObject >( mxStorage, UNO_QUERY_THROW )->commit();
+ // re-insert this storage into the parent storage
+ if( mpParentStorage )
+ {
+ if( mpParentStorage->mxStorage->hasByName( getName() ) )
+ {
+ // replaceByName() does not work (#i109539#)
+ mpParentStorage->mxStorage->removeByName( getName() );
+ Reference< XTransactedObject >( mpParentStorage->mxStorage, UNO_QUERY_THROW )->commit();
+ }
+ mpParentStorage->mxStorage->insertByName( getName(), Any( mxStorage ) );
+ // this requires another commit(), which will be performed by the parent storage
+ }
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+// ============================================================================
+
+} // namespace ole
+} // namespace oox
diff --git a/oox/source/ole/vbacontrol.cxx b/oox/source/ole/vbacontrol.cxx
new file mode 100755
index 000000000000..b43e8289a592
--- /dev/null
+++ b/oox/source/ole/vbacontrol.cxx
@@ -0,0 +1,811 @@
+/*************************************************************************
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "oox/ole/vbacontrol.hxx"
+#include <algorithm>
+#include <set>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/awt/XControlModel.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/io/XInputStreamProvider.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <xmlscript/xmldlg_imexp.hxx>
+#include "properties.hxx"
+#include "tokens.hxx"
+#include "oox/helper/attributelist.hxx"
+#include "oox/helper/binaryinputstream.hxx"
+#include "oox/helper/propertymap.hxx"
+#include "oox/helper/propertyset.hxx"
+#include "oox/helper/storagebase.hxx"
+#include "oox/helper/textinputstream.hxx"
+#include "oox/ole/vbahelper.hxx"
+
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+using ::com::sun::star::awt::XControlModel;
+using ::com::sun::star::container::XNameContainer;
+using ::com::sun::star::io::XInputStreamProvider;
+using ::com::sun::star::lang::XMultiServiceFactory;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Exception;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::UNO_QUERY_THROW;
+using ::com::sun::star::uno::UNO_SET_THROW;
+using ::com::sun::star::uno::XComponentContext;
+
+namespace oox {
+namespace ole {
+
+// ============================================================================
+
+namespace {
+
+const sal_uInt16 VBA_SITE_CLASSIDINDEX = 0x8000;
+const sal_uInt16 VBA_SITE_INDEXMASK = 0x7FFF;
+const sal_uInt16 VBA_SITE_FORM = 7;
+const sal_uInt16 VBA_SITE_IMAGE = 12;
+const sal_uInt16 VBA_SITE_FRAME = 14;
+const sal_uInt16 VBA_SITE_SPINBUTTON = 16;
+const sal_uInt16 VBA_SITE_COMMANDBUTTON = 17;
+const sal_uInt16 VBA_SITE_TABSTRIP = 18;
+const sal_uInt16 VBA_SITE_LABEL = 21;
+const sal_uInt16 VBA_SITE_TEXTBOX = 23;
+const sal_uInt16 VBA_SITE_LISTBOX = 24;
+const sal_uInt16 VBA_SITE_COMBOBOX = 25;
+const sal_uInt16 VBA_SITE_CHECKBOX = 26;
+const sal_uInt16 VBA_SITE_OPTIONBUTTON = 27;
+const sal_uInt16 VBA_SITE_TOGGLEBUTTON = 28;
+const sal_uInt16 VBA_SITE_SCROLLBAR = 47;
+const sal_uInt16 VBA_SITE_MULTIPAGE = 57;
+const sal_uInt16 VBA_SITE_UNKNOWN = 0x7FFF;
+
+const sal_uInt32 VBA_SITE_TABSTOP = 0x00000001;
+const sal_uInt32 VBA_SITE_VISIBLE = 0x00000002;
+const sal_uInt32 VBA_SITE_DEFAULTBUTTON = 0x00000004;
+const sal_uInt32 VBA_SITE_CANCELBUTTON = 0x00000008;
+const sal_uInt32 VBA_SITE_OSTREAM = 0x00000010;
+const sal_uInt32 VBA_SITE_DEFFLAGS = 0x00000033;
+
+const sal_uInt8 VBA_SITEINFO_COUNT = 0x80;
+const sal_uInt8 VBA_SITEINFO_MASK = 0x7F;
+
+// ----------------------------------------------------------------------------
+
+/** Collects names of all controls in a user form or container control. Allows
+ to generate unused names for dummy controls separating option groups.
+ */
+class VbaControlNamesSet
+{
+public:
+ explicit VbaControlNamesSet();
+
+ /** Inserts the name of the passed control. */
+ void insertName( const VbaFormControl& rControl );
+ /** Returns a name that is not contained in this set. */
+ OUString generateDummyName();
+
+private:
+ typedef ::std::set< OUString > OUStringSet;
+ OUStringSet maCtrlNames;
+ const OUString maDummyBaseName;
+ sal_Int32 mnIndex;
+};
+
+VbaControlNamesSet::VbaControlNamesSet() :
+ maDummyBaseName( CREATE_OUSTRING( "DummyGroupSep" ) ),
+ mnIndex( 0 )
+{
+}
+
+void VbaControlNamesSet::insertName( const VbaFormControl& rControl )
+{
+ OUString aName = rControl.getControlName();
+ if( aName.getLength() > 0 )
+ maCtrlNames.insert( aName );
+}
+
+OUString VbaControlNamesSet::generateDummyName()
+{
+ OUString aCtrlName;
+ do
+ {
+ aCtrlName = OUStringBuffer( maDummyBaseName ).append( ++mnIndex ).makeStringAndClear();
+ }
+ while( maCtrlNames.count( aCtrlName ) > 0 );
+ maCtrlNames.insert( aCtrlName );
+ return aCtrlName;
+}
+
+// ----------------------------------------------------------------------------
+
+/** Functor that inserts the name of a control into a VbaControlNamesSet. */
+struct VbaControlNameInserter
+{
+public:
+ VbaControlNamesSet& mrCtrlNames;
+ inline explicit VbaControlNameInserter( VbaControlNamesSet& rCtrlNames ) : mrCtrlNames( rCtrlNames ) {}
+ inline void operator()( const VbaFormControl& rControl ) { mrCtrlNames.insertName( rControl ); }
+};
+
+// ----------------------------------------------------------------------------
+
+/** A dummy invisible form control (fixed label without text) that is used to
+ separate two groups of option buttons.
+ */
+class VbaDummyFormControl : public VbaFormControl
+{
+public:
+ explicit VbaDummyFormControl( const OUString& rName );
+};
+
+VbaDummyFormControl::VbaDummyFormControl( const OUString& rName )
+{
+ mxSiteModel.reset( new VbaSiteModel );
+ mxSiteModel->importProperty( XML_Name, rName );
+ mxSiteModel->importProperty( XML_VariousPropertyBits, OUString( sal_Unicode( '0' ) ) );
+
+ mxCtrlModel.reset( new AxLabelModel );
+ mxCtrlModel->setAwtModelMode();
+ mxCtrlModel->importProperty( XML_Size, CREATE_OUSTRING( "10;10" ) );
+}
+
+} // namespace
+
+// ============================================================================
+
+VbaSiteModel::VbaSiteModel() :
+ maPos( 0, 0 ),
+ mnId( 0 ),
+ mnHelpContextId( 0 ),
+ mnFlags( VBA_SITE_DEFFLAGS ),
+ mnStreamLen( 0 ),
+ mnTabIndex( -1 ),
+ mnClassIdOrCache( VBA_SITE_UNKNOWN ),
+ mnGroupId( 0 )
+{
+}
+
+VbaSiteModel::~VbaSiteModel()
+{
+}
+
+void VbaSiteModel::importProperty( sal_Int32 nPropId, const OUString& rValue )
+{
+ switch( nPropId )
+ {
+ case XML_Name: maName = rValue; break;
+ case XML_Tag: maTag = rValue; break;
+ case XML_VariousPropertyBits: mnFlags = AttributeList::decodeUnsigned( rValue ); break;
+ }
+}
+
+bool VbaSiteModel::importBinaryModel( BinaryInputStream& rInStrm )
+{
+ AxBinaryPropertyReader aReader( rInStrm );
+ aReader.readStringProperty( maName );
+ aReader.readStringProperty( maTag );
+ aReader.readIntProperty< sal_Int32 >( mnId );
+ aReader.readIntProperty< sal_Int32 >( mnHelpContextId );
+ aReader.readIntProperty< sal_uInt32 >( mnFlags );
+ aReader.readIntProperty< sal_uInt32 >( mnStreamLen );
+ aReader.readIntProperty< sal_Int16 >( mnTabIndex );
+ aReader.readIntProperty< sal_uInt16 >( mnClassIdOrCache );
+ aReader.readPairProperty( maPos );
+ aReader.readIntProperty< sal_uInt16 >( mnGroupId );
+ aReader.skipUndefinedProperty();
+ aReader.readStringProperty( maToolTip );
+ aReader.skipStringProperty(); // license key
+ aReader.readStringProperty( maLinkedCell );
+ aReader.readStringProperty( maSourceRange );
+ return aReader.finalizeImport();
+}
+
+void VbaSiteModel::moveRelative( const AxPairData& rDistance )
+{
+ maPos.first += rDistance.first;
+ maPos.second += rDistance.second;
+}
+
+bool VbaSiteModel::isContainer() const
+{
+ return !getFlag( mnFlags, VBA_SITE_OSTREAM );
+}
+
+sal_uInt32 VbaSiteModel::getStreamLength() const
+{
+ return isContainer() ? 0 : mnStreamLen;
+}
+
+OUString VbaSiteModel::getSubStorageName() const
+{
+ if( mnId >= 0 )
+ {
+ OUStringBuffer aBuffer;
+ aBuffer.append( sal_Unicode( 'i' ) );
+ if( mnId < 10 )
+ aBuffer.append( sal_Unicode( '0' ) );
+ aBuffer.append( mnId );
+ return aBuffer.makeStringAndClear();
+ }
+ return OUString();
+}
+
+ControlModelRef VbaSiteModel::createControlModel( const AxClassTable& rClassTable ) const
+{
+ ControlModelRef xCtrlModel;
+
+ sal_Int32 nTypeIndex = static_cast< sal_Int32 >( mnClassIdOrCache & VBA_SITE_INDEXMASK );
+ if( !getFlag( mnClassIdOrCache, VBA_SITE_CLASSIDINDEX ) )
+ {
+ switch( nTypeIndex )
+ {
+ case VBA_SITE_COMMANDBUTTON: xCtrlModel.reset( new AxCommandButtonModel ); break;
+ case VBA_SITE_LABEL: xCtrlModel.reset( new AxLabelModel ); break;
+ case VBA_SITE_IMAGE: xCtrlModel.reset( new AxImageModel ); break;
+ case VBA_SITE_TOGGLEBUTTON: xCtrlModel.reset( new AxToggleButtonModel ); break;
+ case VBA_SITE_CHECKBOX: xCtrlModel.reset( new AxCheckBoxModel ); break;
+ case VBA_SITE_OPTIONBUTTON: xCtrlModel.reset( new AxOptionButtonModel ); break;
+ case VBA_SITE_TEXTBOX: xCtrlModel.reset( new AxTextBoxModel ); break;
+ case VBA_SITE_LISTBOX: xCtrlModel.reset( new AxListBoxModel ); break;
+ case VBA_SITE_COMBOBOX: xCtrlModel.reset( new AxComboBoxModel ); break;
+ case VBA_SITE_SPINBUTTON: /*xCtrlModel.reset( new AxSpinButtonModel );*/ break; // not supported (?)
+ case VBA_SITE_SCROLLBAR: xCtrlModel.reset( new AxScrollBarModel ); break;
+ case VBA_SITE_TABSTRIP: break; // not supported
+ case VBA_SITE_FRAME: xCtrlModel.reset( new AxFrameModel ); break;
+ case VBA_SITE_MULTIPAGE: break; // not supported
+ case VBA_SITE_FORM: break; // not supported
+ default: OSL_ENSURE( false, "VbaSiteModel::createControlModel - unknown type index" );
+ }
+ }
+ else
+ {
+ const OUString* pGuid = ContainerHelper::getVectorElement( rClassTable, nTypeIndex );
+ OSL_ENSURE( pGuid, "VbaSiteModel::createControlModel - invalid class table index" );
+ if( pGuid )
+ {
+ if( pGuid->equalsAscii( COMCTL_GUID_SCROLLBAR_60 ) )
+ xCtrlModel.reset( new ComCtlScrollBarModel( 6 ) );
+ else if( pGuid->equalsAscii( COMCTL_GUID_PROGRESSBAR_50 ) )
+ xCtrlModel.reset( new ComCtlProgressBarModel( 5 ) );
+ else if( pGuid->equalsAscii( COMCTL_GUID_PROGRESSBAR_60 ) )
+ xCtrlModel.reset( new ComCtlProgressBarModel( 6 ) );
+ }
+ }
+
+ if( xCtrlModel.get() )
+ {
+ // user form controls are AWT models
+ xCtrlModel->setAwtModelMode();
+
+ // check that container model matches container flag in site data
+ bool bModelIsContainer = dynamic_cast< const AxContainerModelBase* >( xCtrlModel.get() ) != 0;
+ bool bTypeMatch = bModelIsContainer == isContainer();
+ OSL_ENSURE( bTypeMatch, "VbaSiteModel::createControlModel - container type does not match container flag" );
+ if( !bTypeMatch )
+ xCtrlModel.reset();
+ }
+ return xCtrlModel;
+}
+
+void VbaSiteModel::convertProperties( PropertyMap& rPropMap,
+ const ControlConverter& rConv, ApiControlType eCtrlType, sal_Int32 nCtrlIndex ) const
+{
+ rPropMap.setProperty( PROP_Name, maName );
+ rPropMap.setProperty( PROP_Tag, maTag );
+
+ if( eCtrlType != API_CONTROL_DIALOG )
+ {
+ rPropMap.setProperty( PROP_HelpText, maToolTip );
+ rPropMap.setProperty( PROP_EnableVisible, getFlag( mnFlags, VBA_SITE_VISIBLE ) );
+ // we need to set the passed control index to make option button groups work
+ if( (0 <= nCtrlIndex) && (nCtrlIndex <= SAL_MAX_INT16) )
+ rPropMap.setProperty( PROP_TabIndex, static_cast< sal_Int16 >( nCtrlIndex ) );
+ // progress bar and group box support TabIndex, but not Tabstop...
+ if( (eCtrlType != API_CONTROL_PROGRESSBAR) && (eCtrlType != API_CONTROL_GROUPBOX) )
+ rPropMap.setProperty( PROP_Tabstop, getFlag( mnFlags, VBA_SITE_TABSTOP ) );
+ rConv.convertPosition( rPropMap, maPos );
+ }
+}
+
+// ============================================================================
+
+VbaFormControl::VbaFormControl()
+{
+}
+
+VbaFormControl::~VbaFormControl()
+{
+}
+
+void VbaFormControl::importModelOrStorage( BinaryInputStream& rInStrm, StorageBase& rStrg, const AxClassTable& rClassTable )
+{
+ if( mxSiteModel.get() )
+ {
+ if( mxSiteModel->isContainer() )
+ {
+ StorageRef xSubStrg = rStrg.openSubStorage( mxSiteModel->getSubStorageName(), false );
+ OSL_ENSURE( xSubStrg.get(), "VbaFormControl::importModelOrStorage - cannot find storage for embedded control" );
+ if( xSubStrg.get() )
+ importStorage( *xSubStrg, rClassTable );
+ }
+ else if( !rInStrm.isEof() )
+ {
+ sal_Int64 nNextStrmPos = rInStrm.tell() + mxSiteModel->getStreamLength();
+ importControlModel( rInStrm, rClassTable );
+ rInStrm.seek( nNextStrmPos );
+ }
+ }
+}
+
+OUString VbaFormControl::getControlName() const
+{
+ return mxSiteModel.get() ? mxSiteModel->getName() : OUString();
+}
+
+void VbaFormControl::createAndConvert( sal_Int32 nCtrlIndex,
+ const Reference< XNameContainer >& rxParentNC, const ControlConverter& rConv ) const
+{
+ if( rxParentNC.is() && mxSiteModel.get() && mxCtrlModel.get() ) try
+ {
+ // create the control model
+ OUString aServiceName = mxCtrlModel->getServiceName();
+ Reference< XMultiServiceFactory > xModelFactory( rxParentNC, UNO_QUERY_THROW );
+ Reference< XControlModel > xCtrlModel( xModelFactory->createInstance( aServiceName ), UNO_QUERY_THROW );
+
+ // convert all properties and embedded controls
+ if( convertProperties( xCtrlModel, rConv, nCtrlIndex ) )
+ {
+ // insert into parent container
+ const OUString& rCtrlName = mxSiteModel->getName();
+ OSL_ENSURE( !rxParentNC->hasByName( rCtrlName ), "VbaFormControl::createAndConvert - multiple controls with equal name" );
+ ContainerHelper::insertByName( rxParentNC, rCtrlName, Any( xCtrlModel ) );
+ }
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+// protected ------------------------------------------------------------------
+
+void VbaFormControl::importControlModel( BinaryInputStream& rInStrm, const AxClassTable& rClassTable )
+{
+ createControlModel( rClassTable );
+ if( mxCtrlModel.get() )
+ mxCtrlModel->importBinaryModel( rInStrm );
+}
+
+void VbaFormControl::importStorage( StorageBase& rStrg, const AxClassTable& rClassTable )
+{
+ createControlModel( rClassTable );
+ AxContainerModelBase* pContainerModel = dynamic_cast< AxContainerModelBase* >( mxCtrlModel.get() );
+ OSL_ENSURE( pContainerModel, "VbaFormControl::importStorage - missing container control model" );
+ if( pContainerModel )
+ {
+ /* Open the 'f' stream containing the model of this control and a list
+ of site models for all child controls. */
+ BinaryXInputStream aFStrm( rStrg.openInputStream( CREATE_OUSTRING( "f" ) ), true );
+ OSL_ENSURE( !aFStrm.isEof(), "VbaFormControl::importStorage - missing 'f' stream" );
+
+ /* Read the properties of this container control and the class table
+ (into the maClassTable vector) containing a list of GUIDs for
+ exotic embedded controls. */
+ if( !aFStrm.isEof() && pContainerModel->importBinaryModel( aFStrm ) && pContainerModel->importClassTable( aFStrm, maClassTable ) )
+ {
+ /* Read the site models of all embedded controls (this fills the
+ maControls vector). Ignore failure of importSiteModels() but
+ try to import as much controls as possible. */
+ importEmbeddedSiteModels( aFStrm );
+
+ /* Open the 'o' stream containing models of embedded simple
+ controls. Stream may be empty or missing, if this control
+ contains no controls or only container controls. */
+ BinaryXInputStream aOStrm( rStrg.openInputStream( CREATE_OUSTRING( "o" ) ), true );
+
+ /* Iterate over all embedded controls, import model from 'o'
+ stream (for embedded simple controls) or from the substorage
+ (for embedded container controls). */
+ maControls.forEachMem( &VbaFormControl::importModelOrStorage,
+ ::boost::ref( aOStrm ), ::boost::ref( rStrg ), ::boost::cref( maClassTable ) );
+
+ /* Reorder the controls (sorts all option buttons of an option
+ group together), and move all children of all embedded frames
+ (group boxes) to this control (UNO group boxes cannot contain
+ other controls). */
+ finalizeEmbeddedControls();
+ }
+ }
+}
+
+bool VbaFormControl::convertProperties( const Reference< XControlModel >& rxCtrlModel,
+ const ControlConverter& rConv, sal_Int32 nCtrlIndex ) const
+{
+ if( rxCtrlModel.is() && mxSiteModel.get() && mxCtrlModel.get() )
+ {
+ const OUString& rCtrlName = mxSiteModel->getName();
+ OSL_ENSURE( rCtrlName.getLength() > 0, "VbaFormControl::convertProperties - control without name" );
+ if( rCtrlName.getLength() > 0 )
+ {
+ // convert all properties
+ PropertyMap aPropMap;
+ mxSiteModel->convertProperties( aPropMap, rConv, mxCtrlModel->getControlType(), nCtrlIndex );
+ mxCtrlModel->convertProperties( aPropMap, rConv );
+ mxCtrlModel->convertSize( aPropMap, rConv );
+ PropertySet aPropSet( rxCtrlModel );
+ aPropSet.setProperties( aPropMap );
+
+ // create and convert all embedded controls
+ if( !maControls.empty() ) try
+ {
+ Reference< XNameContainer > xCtrlModelNC( rxCtrlModel, UNO_QUERY_THROW );
+ /* Call conversion for all controls. Pass vector index as new
+ tab order to make option button groups work correctly. */
+ maControls.forEachMemWithIndex( &VbaFormControl::createAndConvert,
+ ::boost::cref( xCtrlModelNC ), ::boost::cref( rConv ) );
+ }
+ catch( Exception& )
+ {
+ OSL_ENSURE( false, "VbaFormControl::convertProperties - cannot get control container interface" );
+ }
+
+ return true;
+ }
+ }
+ return false;
+}
+
+// private --------------------------------------------------------------------
+
+void VbaFormControl::createControlModel( const AxClassTable& rClassTable )
+{
+ // derived classes may have created their own control model
+ if( !mxCtrlModel && mxSiteModel.get() )
+ mxCtrlModel = mxSiteModel->createControlModel( rClassTable );
+}
+
+bool VbaFormControl::importSiteModel( BinaryInputStream& rInStrm )
+{
+ mxSiteModel.reset( new VbaSiteModel );
+ return mxSiteModel->importBinaryModel( rInStrm );
+}
+
+bool VbaFormControl::importEmbeddedSiteModels( BinaryInputStream& rInStrm )
+{
+ sal_uInt64 nAnchorPos = rInStrm.tell();
+ sal_uInt32 nSiteCount, nSiteDataSize;
+ rInStrm >> nSiteCount >> nSiteDataSize;
+ sal_Int64 nSiteEndPos = rInStrm.tell() + nSiteDataSize;
+
+ // skip the site info structure
+ sal_uInt32 nSiteIndex = 0;
+ while( !rInStrm.isEof() && (nSiteIndex < nSiteCount) )
+ {
+ rInStrm.skip( 1 ); // site depth
+ sal_uInt8 nTypeCount = rInStrm.readuInt8(); // 'type-or-count' byte
+ if( getFlag( nTypeCount, VBA_SITEINFO_COUNT ) )
+ {
+ /* Count flag is set: the 'type-or-count' byte contains the number
+ of controls in the lower bits, the type specifier follows in
+ the next byte. The type specifier should always be 1 according
+ to the specification. */
+ rInStrm.skip( 1 );
+ nSiteIndex += (nTypeCount & VBA_SITEINFO_MASK);
+ }
+ else
+ {
+ /* Count flag is not set: the 'type-or-count' byte contains the
+ type specifier of *one* control in the lower bits (this type
+ should be 1, see above). */
+ ++nSiteIndex;
+ }
+ }
+ // align the stream to 32bit, relative to start of entire site info
+ rInStrm.alignToBlock( 4, nAnchorPos );
+
+ // import the site models for all embedded controls
+ maControls.clear();
+ bool bValid = !rInStrm.isEof();
+ for( nSiteIndex = 0; bValid && (nSiteIndex < nSiteCount); ++nSiteIndex )
+ {
+ VbaFormControlRef xControl( new VbaFormControl );
+ maControls.push_back( xControl );
+ bValid = xControl->importSiteModel( rInStrm );
+ }
+
+ rInStrm.seek( nSiteEndPos );
+ return bValid;
+}
+
+void VbaFormControl::finalizeEmbeddedControls()
+{
+ /* This function performs two tasks:
+
+ 1) Reorder the controls appropriately (sort all option buttons of an
+ option group together to make grouping work).
+ 2) Move all children of all embedded frames (group boxes) to this
+ control (UNO group boxes cannot contain other controls).
+ */
+
+ // first, sort all controls by original tab index
+ ::std::sort( maControls.begin(), maControls.end(), &compareByTabIndex );
+
+ /* Collect the programmatical names of all embedded controls (needed to be
+ able to set unused names to new dummy controls created below). Also
+ collect the names of all children of embedded frames (group boxes).
+ Luckily, names of controls must be unique in the entire form, not just
+ in the current container. */
+ VbaControlNamesSet aControlNames;
+ VbaControlNameInserter aInserter( aControlNames );
+ maControls.forEach( aInserter );
+ for( VbaFormControlVector::iterator aIt = maControls.begin(), aEnd = maControls.end(); aIt != aEnd; ++aIt )
+ if( (*aIt)->mxCtrlModel.get() && ((*aIt)->mxCtrlModel->getControlType() == API_CONTROL_GROUPBOX) )
+ (*aIt)->maControls.forEach( aInserter );
+
+ /* Reprocess the sorted list and collect all option button controls that
+ are part of the same option group (determined by group name). All
+ controls will be stored in a vector of vectors, that collects every
+ option button group in one vector element, and other controls between
+ these option groups (or leading or trailing controls) in other vector
+ elements. If an option button group follows another group, a dummy
+ separator control has to be inserted. */
+ typedef RefVector< VbaFormControlVector > VbaFormControlVectorVector;
+ VbaFormControlVectorVector aControlGroups;
+
+ typedef RefMap< OUString, VbaFormControlVector > VbaFormControlVectorMap;
+ VbaFormControlVectorMap aOptionGroups;
+
+ typedef VbaFormControlVectorMap::mapped_type VbaFormControlVectorRef;
+ bool bLastWasOptionButton = false;
+ for( VbaFormControlVector::iterator aIt = maControls.begin(), aEnd = maControls.end(); aIt != aEnd; ++aIt )
+ {
+ VbaFormControlRef xControl = *aIt;
+ const ControlModelBase* pCtrlModel = xControl->mxCtrlModel.get();
+
+ if( const AxOptionButtonModel* pOptButtonModel = dynamic_cast< const AxOptionButtonModel* >( pCtrlModel ) )
+ {
+ // check if a new option group needs to be created
+ const OUString& rGroupName = pOptButtonModel->getGroupName();
+ VbaFormControlVectorRef& rxOptionGroup = aOptionGroups[ rGroupName ];
+ if( !rxOptionGroup )
+ {
+ /* If last control was an option button too, we have two
+ option groups following each other, so a dummy separator
+ control is needed. */
+ if( bLastWasOptionButton )
+ {
+ VbaFormControlVectorRef xDummyGroup( new VbaFormControlVector );
+ aControlGroups.push_back( xDummyGroup );
+ OUString aName = aControlNames.generateDummyName();
+ VbaFormControlRef xDummyControl( new VbaDummyFormControl( aName ) );
+ xDummyGroup->push_back( xDummyControl );
+ }
+ rxOptionGroup.reset( new VbaFormControlVector );
+ aControlGroups.push_back( rxOptionGroup );
+ }
+ /* Append the option button to the control group (which is now
+ referred by the vector aControlGroups and by the map
+ aOptionGroups). */
+ rxOptionGroup->push_back( xControl );
+ bLastWasOptionButton = true;
+ }
+ else
+ {
+ // open a new control group, if the last group is an option group
+ if( bLastWasOptionButton || aControlGroups.empty() )
+ {
+ VbaFormControlVectorRef xControlGroup( new VbaFormControlVector );
+ aControlGroups.push_back( xControlGroup );
+ }
+ // append the control to the last control group
+ VbaFormControlVector& rLastGroup = *aControlGroups.back();
+ rLastGroup.push_back( xControl );
+ bLastWasOptionButton = false;
+
+ // if control is a group box, move all its children to this control
+ if( pCtrlModel && (pCtrlModel->getControlType() == API_CONTROL_GROUPBOX) )
+ {
+ /* Move all embedded controls of the group box relative to the
+ position of the group box. */
+ xControl->moveEmbeddedToAbsoluteParent();
+ /* Insert all children of the group box into the last control
+ group (following the group box). */
+ rLastGroup.insert( rLastGroup.end(), xControl->maControls.begin(), xControl->maControls.end() );
+ xControl->maControls.clear();
+ // check if last control of the group box is an option button
+ bLastWasOptionButton = dynamic_cast< const AxOptionButtonModel* >( rLastGroup.back()->mxCtrlModel.get() ) != 0;
+ }
+ }
+ }
+
+ // flatten the vector of vectors of form controls to a single vector
+ maControls.clear();
+ for( VbaFormControlVectorVector::iterator aIt = aControlGroups.begin(), aEnd = aControlGroups.end(); aIt != aEnd; ++aIt )
+ maControls.insert( maControls.end(), (*aIt)->begin(), (*aIt)->end() );
+}
+
+void VbaFormControl::moveRelative( const AxPairData& rDistance )
+{
+ if( mxSiteModel.get() )
+ mxSiteModel->moveRelative( rDistance );
+}
+
+void VbaFormControl::moveEmbeddedToAbsoluteParent()
+{
+ if( mxSiteModel.get() && !maControls.empty() )
+ {
+ // distance to move is equal to position of this control in its parent
+ AxPairData aDistance = mxSiteModel->getPosition();
+
+ /* For group boxes: add half of the font height to Y position (VBA
+ positions relative to frame border line, not to 'top' of frame). */
+ const AxFontDataModel* pFontModel = dynamic_cast< const AxFontDataModel* >( mxCtrlModel.get() );
+ if( pFontModel && (pFontModel->getControlType() == API_CONTROL_GROUPBOX) )
+ {
+ // convert points to 1/100 mm (1 pt = 1/72 inch = 2.54/72 cm = 2540/72 1/100 mm)
+ sal_Int32 nFontHeight = static_cast< sal_Int32 >( pFontModel->getFontHeight() * 2540 / 72 );
+ aDistance.second += nFontHeight / 2;
+ }
+
+ // move the embedded controls
+ maControls.forEachMem( &VbaFormControl::moveRelative, ::boost::cref( aDistance ) );
+ }
+}
+
+/*static*/ bool VbaFormControl::compareByTabIndex( const VbaFormControlRef& rxLeft, const VbaFormControlRef& rxRight )
+{
+ // sort controls without model to the end
+ sal_Int32 nLeftTabIndex = rxLeft->mxSiteModel.get() ? rxLeft->mxSiteModel->getTabIndex() : SAL_MAX_INT32;
+ sal_Int32 nRightTabIndex = rxRight->mxSiteModel.get() ? rxRight->mxSiteModel->getTabIndex() : SAL_MAX_INT32;
+ return nLeftTabIndex < nRightTabIndex;
+}
+
+// ============================================================================
+
+namespace {
+
+OUString lclGetQuotedString( const OUString& rCodeLine )
+{
+ OUStringBuffer aBuffer;
+ sal_Int32 nLen = rCodeLine.getLength();
+ if( (nLen > 0) && (rCodeLine[ 0 ] == '"') )
+ {
+ bool bExitLoop = false;
+ for( sal_Int32 nIndex = 1; !bExitLoop && (nIndex < nLen); ++nIndex )
+ {
+ sal_Unicode cChar = rCodeLine[ nIndex ];
+ // exit on closing quote char (but check on double quote chars)
+ bExitLoop = (cChar == '"') && ((nIndex + 1 == nLen) || (rCodeLine[ nIndex + 1 ] != '"'));
+ if( !bExitLoop )
+ {
+ aBuffer.append( cChar );
+ // skip second quote char
+ if( cChar == '"' )
+ ++nIndex;
+ }
+ }
+ }
+ return aBuffer.makeStringAndClear();
+}
+
+} // namespace
+
+// ----------------------------------------------------------------------------
+
+VbaUserForm::VbaUserForm( const Reference< XMultiServiceFactory >& rxGlobalFactory,
+ const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr ) :
+ ControlConverter( rGraphicHelper, bDefaultColorBgr ),
+ mxGlobalFactory( rxGlobalFactory )
+{
+ OSL_ENSURE( mxGlobalFactory.is(), "VbaUserForm::VbaUserForm - missing service factory" );
+}
+
+void VbaUserForm::importForm( const Reference< XNameContainer >& rxDialogLib,
+ StorageBase& rVbaFormStrg, const OUString& rModuleName, rtl_TextEncoding eTextEnc )
+{
+ OSL_ENSURE( rxDialogLib.is(), "VbaUserForm::importForm - missing dialog library" );
+ if( !mxGlobalFactory.is() || !rxDialogLib.is() )
+ return;
+
+ // check that the '03VBFrame' stream exists, this is required for forms
+ BinaryXInputStream aInStrm( rVbaFormStrg.openInputStream( CREATE_OUSTRING( "\003VBFrame" ) ), true );
+ OSL_ENSURE( !aInStrm.isEof(), "VbaUserForm::importForm - missing \\003VBFrame stream" );
+ if( aInStrm.isEof() )
+ return;
+
+ // scan for the line 'Begin {GUID} <FormName>'
+ TextInputStream aFrameTextStrm( aInStrm, eTextEnc );
+ const OUString aBegin = CREATE_OUSTRING( "Begin" );
+ OUString aLine;
+ bool bBeginFound = false;
+ while( !bBeginFound && !aFrameTextStrm.isEof() )
+ {
+ aLine = aFrameTextStrm.readLine().trim();
+ bBeginFound = VbaHelper::eatKeyword( aLine, aBegin );
+ }
+ // check for the specific GUID that represents VBA forms
+ if( !bBeginFound || !VbaHelper::eatKeyword( aLine, CREATE_OUSTRING( "{C62A69F0-16DC-11CE-9E98-00AA00574A4F}" ) ) )
+ return;
+
+ // remaining line is the form name
+ OUString aFormName = aLine.trim();
+ OSL_ENSURE( aFormName.getLength() > 0, "VbaUserForm::importForm - missing form name" );
+ OSL_ENSURE( rModuleName.equalsIgnoreAsciiCase( aFormName ), "VbaUserForm::importFrameStream - form and module name mismatch" );
+ if( aFormName.getLength() == 0 )
+ aFormName = rModuleName;
+ if( aFormName.getLength() == 0 )
+ return;
+ mxSiteModel.reset( new VbaSiteModel );
+ mxSiteModel->importProperty( XML_Name, aFormName );
+
+ // read the form properties (caption is contained in this '03VBFrame' stream, not in the 'f' stream)
+ mxCtrlModel.reset( new AxUserFormModel );
+ OUString aKey, aValue;
+ bool bExitLoop = false;
+ while( !bExitLoop && !aFrameTextStrm.isEof() )
+ {
+ aLine = aFrameTextStrm.readLine().trim();
+ bExitLoop = aLine.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "End" ) );
+ if( !bExitLoop && VbaHelper::extractKeyValue( aKey, aValue, aLine ) )
+ {
+ if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "Caption" ) ) )
+ mxCtrlModel->importProperty( XML_Caption, lclGetQuotedString( aValue ) );
+ else if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "Tag" ) ) )
+ mxSiteModel->importProperty( XML_Tag, lclGetQuotedString( aValue ) );
+ }
+ }
+
+ // use generic container control functionality to import the embedded controls
+ importStorage( rVbaFormStrg, AxClassTable() );
+
+ try
+ {
+ // create the dialog model
+ OUString aServiceName = mxCtrlModel->getServiceName();
+ Reference< XControlModel > xDialogModel( mxGlobalFactory->createInstance( aServiceName ), UNO_QUERY_THROW );
+ Reference< XNameContainer > xDialogNC( xDialogModel, UNO_QUERY_THROW );
+
+ // convert properties and embedded controls
+ if( convertProperties( xDialogModel, *this, 0 ) )
+ {
+ // export the dialog to XML and insert it into the dialog library
+ PropertySet aFactoryProps( mxGlobalFactory );
+ Reference< XComponentContext > xCompContext( aFactoryProps.getAnyProperty( PROP_DefaultContext ), UNO_QUERY_THROW );
+ Reference< XInputStreamProvider > xDialogSource( ::xmlscript::exportDialogModel( xDialogNC, xCompContext ), UNO_SET_THROW );
+ OSL_ENSURE( !rxDialogLib->hasByName( aFormName ), "VbaUserForm::importForm - multiple dialogs with equal name" );
+ ContainerHelper::insertByName( rxDialogLib, aFormName, Any( xDialogSource ) );
+ }
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+// ============================================================================
+
+} // namespace ole
+} // namespace oox
diff --git a/oox/source/ole/vbahelper.cxx b/oox/source/ole/vbahelper.cxx
new file mode 100755
index 000000000000..7293e357e746
--- /dev/null
+++ b/oox/source/ole/vbahelper.cxx
@@ -0,0 +1,248 @@
+/*************************************************************************
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "oox/ole/vbahelper.hxx"
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/document/XEventsSupplier.hpp>
+#include <comphelper/string.hxx>
+#include "oox/helper/binaryinputstream.hxx"
+
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+using ::com::sun::star::beans::PropertyValue;
+using ::com::sun::star::container::XNameContainer;
+using ::com::sun::star::container::XNameReplace;
+using ::com::sun::star::document::XEventsSupplier;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Exception;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::UNO_SET_THROW;
+
+namespace oox {
+namespace ole {
+
+// ============================================================================
+
+/*static*/ OUString VbaHelper::getBasicScriptUrl(
+ const OUString& rLibraryName, const OUString& rModuleName, const OUString& rMacroName )
+{
+ OSL_ENSURE( rLibraryName.getLength() > 0, "VbaHelper::getBasicScriptUrl - library name is empty" );
+ OSL_ENSURE( rModuleName.getLength() > 0, "VbaHelper::getBasicScriptUrl - module name is empty" );
+ OSL_ENSURE( rMacroName.getLength() > 0, "VbaHelper::getBasicScriptUrl - macro name is empty" );
+ const sal_Unicode cDot = '.';
+ return OUStringBuffer().
+ appendAscii( RTL_CONSTASCII_STRINGPARAM( "vnd.sun.star.script:" ) ).
+ append( rLibraryName ).append( cDot ).append( rModuleName ).append( cDot ).append( rMacroName ).
+ appendAscii( RTL_CONSTASCII_STRINGPARAM( "?language=Basic&location=document" ) ).
+ makeStringAndClear();
+}
+
+/*static*/ bool VbaHelper::readDirRecord( sal_uInt16& rnRecId, StreamDataSequence& rRecData, BinaryInputStream& rInStrm )
+{
+ // read the record header
+ sal_Int32 nRecSize;
+ rInStrm >> rnRecId >> nRecSize;
+ // for no obvious reason, PROJECTVERSION record contains size field of 4, but is 6 bytes long
+ if( rnRecId == VBA_ID_PROJECTVERSION )
+ {
+ OSL_ENSURE( nRecSize == 4, "VbaHelper::readDirRecord - unexpected record size for PROJECTVERSION" );
+ nRecSize = 6;
+ }
+ // read the record contents into the passed sequence
+ return !rInStrm.isEof() && (rInStrm.readData( rRecData, nRecSize ) == nRecSize);
+}
+
+/*static*/ bool VbaHelper::extractKeyValue( OUString& rKey, OUString& rValue, const OUString& rKeyValue )
+{
+ sal_Int32 nEqSignPos = rKeyValue.indexOf( '=' );
+ if( nEqSignPos > 0 )
+ {
+ rKey = rKeyValue.copy( 0, nEqSignPos ).trim();
+ rValue = rKeyValue.copy( nEqSignPos + 1 ).trim();
+ return (rKey.getLength() > 0) && (rValue.getLength() > 0);
+ }
+ return false;
+}
+
+/*static*/ bool VbaHelper::eatWhitespace( OUString& rCodeLine )
+{
+ sal_Int32 nIndex = 0;
+ while( (nIndex < rCodeLine.getLength()) && ((rCodeLine[ nIndex ] == ' ') || (rCodeLine[ nIndex ] == '\t')) )
+ ++nIndex;
+ if( nIndex > 0 )
+ {
+ rCodeLine = rCodeLine.copy( nIndex );
+ return true;
+ }
+ return false;
+}
+
+/*static*/ bool VbaHelper::eatKeyword( OUString& rCodeLine, const OUString& rKeyword )
+{
+ if( rCodeLine.matchIgnoreAsciiCase( rKeyword ) )
+ {
+ rCodeLine = rCodeLine.copy( rKeyword.getLength() );
+ // success, if code line ends after keyword, or if whitespace follows
+ return (rCodeLine.getLength() == 0) || eatWhitespace( rCodeLine );
+ }
+ return false;
+}
+
+/*static*/ OUString VbaHelper::getSourceCode( const Reference< XNameContainer >& rxBasicLib, const OUString& rModuleName )
+{
+ OUString aSourceCode;
+ if( rxBasicLib.is() ) try
+ {
+ rxBasicLib->getByName( rModuleName ) >>= aSourceCode;
+ }
+ catch( Exception& )
+ {
+ }
+ return aSourceCode;
+}
+
+namespace {
+
+bool lclGetLine( OUString& rCodeLine, sal_Int32& rnIndex, const OUString& rSourceCode )
+{
+ if( rnIndex < rSourceCode.getLength() )
+ {
+ sal_Int32 nPosLF = rSourceCode.indexOf( '\n', rnIndex );
+ if( nPosLF >= rnIndex )
+ {
+ rCodeLine = rSourceCode.copy( rnIndex, nPosLF - rnIndex ).trim();
+ rnIndex = nPosLF + 1;
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
+
+/*static*/ bool VbaHelper::hasMacro( const OUString& rSourceCode, const OUString& rMacroName )
+{
+ // scan all text lines for '[Public|Private] [Static] Sub <macroname> (...)'
+ const OUString aPublic = CREATE_OUSTRING( "Public" );
+ const OUString aPrivate = CREATE_OUSTRING( "Private" );
+ const OUString aStatic = CREATE_OUSTRING( "Static" );
+ const OUString aSub = CREATE_OUSTRING( "Sub" );
+
+ OUString aCodeLine;
+ sal_Int32 nIndex = 0;
+ while( lclGetLine( aCodeLine, nIndex, rSourceCode ) )
+ {
+ // eat optional 'Private' or 'Public', but do not accept both keywords in a row (therefore the ||)
+ eatKeyword( aCodeLine, aPublic ) || eatKeyword( aCodeLine, aPrivate );
+ // eat optional 'Static'
+ eatKeyword( aCodeLine, aStatic );
+ // eat 'Sub' keyword, check if macro name follows
+ if( eatKeyword( aCodeLine, aSub ) && aCodeLine.matchIgnoreAsciiCase( rMacroName ) )
+ {
+ // eat macro name and following whitespace
+ aCodeLine = aCodeLine.copy( rMacroName.getLength() );
+ eatWhitespace( aCodeLine );
+ // opening bracket must follow the macro name
+ if( (aCodeLine.getLength() >= 2) && (aCodeLine[ 0 ] == '(') )
+ return true;
+ }
+ }
+ return false;
+}
+
+/*static*/ bool VbaHelper::hasMacro( const Reference< XNameContainer >& rxBasicLib,
+ const OUString& rModuleName, const OUString& rMacroName )
+{
+ return hasMacro( getSourceCode( rxBasicLib, rModuleName ), rMacroName );
+}
+
+/*static*/ bool VbaHelper::insertMacro( const Reference< XNameContainer >& rxBasicLib, const OUString& rModuleName,
+ const OUString& rMacroName, const OUString& rMacroArgs, const OUString& rMacroType, const OUString& rMacroCode )
+{
+ if( rxBasicLib.is() ) try
+ {
+ // receive module source code and check that the specified macro does not exist
+ OUString aSourceCode = getSourceCode( rxBasicLib, rModuleName );
+ if( !hasMacro( aSourceCode, rMacroName ) )
+ {
+ bool bFunction = rMacroType.getLength() > 0;
+ const sal_Char* pcSubFunc = bFunction ? "Function" : "Sub";
+ OUStringBuffer aBuffer( aSourceCode );
+ // generate the source code for the new macro
+ aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\nPrivate " ) ).
+ appendAscii( pcSubFunc ).append( sal_Unicode( ' ' ) ).
+ append( rMacroName ).append( sal_Unicode( '(' ) );
+ if( rMacroArgs.getLength() > 0 )
+ aBuffer.append( sal_Unicode( ' ' ) ).append( rMacroArgs ).append( sal_Unicode( ' ' ) );
+ aBuffer.append( sal_Unicode( ')' ) );
+ if( bFunction )
+ aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( " As " ) ).append( rMacroType );
+ aBuffer.append( sal_Unicode( '\n' ) );
+ // replace all $MACRO placeholders with macro name
+ if( rMacroCode.getLength() > 0 )
+ {
+ OUString aMacroCode = ::comphelper::string::searchAndReplaceAsciiL( rMacroCode, RTL_CONSTASCII_STRINGPARAM( "$MACRO" ), rMacroName );
+ aBuffer.append( aMacroCode ).append( sal_Unicode( '\n' ) );
+ }
+ aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "End " ) ).appendAscii( pcSubFunc ).append( sal_Unicode( '\n' ) );
+ rxBasicLib->replaceByName( rModuleName, Any( aBuffer.makeStringAndClear() ) );
+ return true;
+ }
+ }
+ catch( Exception& )
+ {
+ }
+ return false;
+}
+
+/*static*/ bool VbaHelper::attachMacroToEvent( const Reference< XEventsSupplier >& rxEventsSupp,
+ const OUString& rEventName, const OUString& rLibraryName, const OUString& rModuleName, const OUString& rMacroName )
+{
+ if( rxEventsSupp.is() ) try
+ {
+ Reference< XNameReplace > xEvents( rxEventsSupp->getEvents(), UNO_SET_THROW );
+ Sequence< PropertyValue > aEvent( 2 );
+ aEvent[ 0 ].Name = CREATE_OUSTRING( "EventType" );
+ aEvent[ 0 ].Value <<= CREATE_OUSTRING( "Script" );
+ aEvent[ 1 ].Name = CREATE_OUSTRING( "Script" );
+ aEvent[ 1 ].Value <<= getBasicScriptUrl( rLibraryName, rModuleName, rMacroName );
+ xEvents->replaceByName( rEventName, Any( aEvent ) );
+ return true;
+ }
+ catch( Exception& )
+ {
+ }
+ return false;
+}
+
+// ============================================================================
+
+} // namespace ole
+} // namespace oox
diff --git a/oox/source/ole/vbamodule.cxx b/oox/source/ole/vbamodule.cxx
new file mode 100755
index 000000000000..e9388e54215a
--- /dev/null
+++ b/oox/source/ole/vbamodule.cxx
@@ -0,0 +1,241 @@
+/*************************************************************************
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "oox/ole/vbamodule.hxx"
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/script/ModuleInfo.hpp>
+#include <com/sun/star/script/ModuleType.hpp>
+#include <com/sun/star/script/XVBAModuleInfo.hpp>
+#include "oox/helper/binaryinputstream.hxx"
+#include "oox/helper/storagebase.hxx"
+#include "oox/helper/textinputstream.hxx"
+#include "oox/ole/vbahelper.hxx"
+#include "oox/ole/vbainputstream.hxx"
+
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+using ::com::sun::star::container::XNameAccess;
+using ::com::sun::star::container::XNameContainer;
+using ::com::sun::star::frame::XModel;
+using ::com::sun::star::script::ModuleInfo;
+using ::com::sun::star::script::XVBAModuleInfo;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Exception;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::uno::UNO_QUERY_THROW;
+
+namespace ApiModuleType = ::com::sun::star::script::ModuleType;
+
+namespace oox {
+namespace ole {
+
+// ============================================================================
+
+VbaModule::VbaModule( const Reference< XModel >& rxDocModel, const OUString& rName, rtl_TextEncoding eTextEnc, bool bExecutable ) :
+ mxDocModel( rxDocModel ),
+ maName( rName ),
+ meTextEnc( eTextEnc ),
+ mnType( ApiModuleType::UNKNOWN ),
+ mnOffset( SAL_MAX_UINT32 ),
+ mbReadOnly( false ),
+ mbPrivate( false ),
+ mbExecutable( bExecutable )
+{
+}
+
+void VbaModule::importDirRecords( BinaryInputStream& rDirStrm )
+{
+ sal_uInt16 nRecId = 0;
+ StreamDataSequence aRecData;
+ while( VbaHelper::readDirRecord( nRecId, aRecData, rDirStrm ) && (nRecId != VBA_ID_MODULEEND) )
+ {
+ SequenceInputStream aRecStrm( aRecData );
+ sal_Int32 nRecSize = aRecData.getLength();
+ switch( nRecId )
+ {
+#define OOX_ENSURE_RECORDSIZE( cond ) OSL_ENSURE( cond, "VbaModule::importDirRecords - invalid record size" )
+ case VBA_ID_MODULENAME:
+ OSL_ENSURE( false, "VbaModule::importDirRecords - unexpected MODULENAME record" );
+ maName = aRecStrm.readCharArrayUC( nRecSize, meTextEnc );
+ break;
+ case VBA_ID_MODULENAMEUNICODE:
+ break;
+ case VBA_ID_MODULESTREAMNAME:
+ maStreamName = aRecStrm.readCharArrayUC( nRecSize, meTextEnc );
+ break;
+ case VBA_ID_MODULESTREAMNAMEUNICODE:
+ break;
+ case VBA_ID_MODULEDOCSTRING:
+ maDocString = aRecStrm.readCharArrayUC( nRecSize, meTextEnc );
+ break;
+ case VBA_ID_MODULEDOCSTRINGUNICODE:
+ break;
+ case VBA_ID_MODULEOFFSET:
+ OOX_ENSURE_RECORDSIZE( nRecSize == 4 );
+ aRecStrm >> mnOffset;
+ break;
+ case VBA_ID_MODULEHELPCONTEXT:
+ OOX_ENSURE_RECORDSIZE( nRecSize == 4 );
+ break;
+ case VBA_ID_MODULECOOKIE:
+ OOX_ENSURE_RECORDSIZE( nRecSize == 2 );
+ break;
+ case VBA_ID_MODULETYPEPROCEDURAL:
+ OOX_ENSURE_RECORDSIZE( nRecSize == 0 );
+ OSL_ENSURE( mnType == ApiModuleType::UNKNOWN, "VbaModule::importDirRecords - multiple module type records" );
+ mnType = ApiModuleType::NORMAL;
+ break;
+ case VBA_ID_MODULETYPEDOCUMENT:
+ OOX_ENSURE_RECORDSIZE( nRecSize == 0 );
+ OSL_ENSURE( mnType == ApiModuleType::UNKNOWN, "VbaModule::importDirRecords - multiple module type records" );
+ mnType = ApiModuleType::DOCUMENT;
+ break;
+ case VBA_ID_MODULEREADONLY:
+ OOX_ENSURE_RECORDSIZE( nRecSize == 0 );
+ mbReadOnly = true;
+ break;
+ case VBA_ID_MODULEPRIVATE:
+ OOX_ENSURE_RECORDSIZE( nRecSize == 0 );
+ mbPrivate = true;
+ break;
+ default:
+ OSL_ENSURE( false, "VbaModule::importDirRecords - unknown module record" );
+#undef OOX_ENSURE_RECORDSIZE
+ }
+ }
+ OSL_ENSURE( maName.getLength() > 0, "VbaModule::importDirRecords - missing module name" );
+ OSL_ENSURE( maStreamName.getLength() > 0, "VbaModule::importDirRecords - missing module stream name" );
+ OSL_ENSURE( mnType != ApiModuleType::UNKNOWN, "VbaModule::importDirRecords - missing module type" );
+ OSL_ENSURE( mnOffset < SAL_MAX_UINT32, "VbaModule::importDirRecords - missing module stream offset" );
+}
+
+void VbaModule::importSourceCode( StorageBase& rVbaStrg,
+ const Reference< XNameContainer >& rxBasicLib, const Reference< XNameAccess >& rxDocObjectNA ) const
+{
+ if( (maName.getLength() == 0) || (maStreamName.getLength() == 0) || (mnOffset == SAL_MAX_UINT32) )
+ return;
+
+ BinaryXInputStream aInStrm( rVbaStrg.openInputStream( maStreamName ), true );
+ OSL_ENSURE( !aInStrm.isEof(), "VbaModule::importSourceCode - cannot open module stream" );
+ // skip the 'performance cache' stored before the actual source code
+ aInStrm.seek( mnOffset );
+ // if stream is still valid, load the source code
+ if( aInStrm.isEof() )
+ return;
+
+ // prepare the Basic module
+ ModuleInfo aModuleInfo;
+ aModuleInfo.ModuleType = mnType;
+ OUStringBuffer aSourceCode;
+ aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Rem Attribute VBA_ModuleType=" ) );
+ switch( mnType )
+ {
+ case ApiModuleType::NORMAL:
+ aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "VBAModule" ) );
+ break;
+ case ApiModuleType::CLASS:
+ aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "VBAClassModule" ) );
+ break;
+ case ApiModuleType::FORM:
+ aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "VBAFormModule" ) );
+ // hack from old filter, document Basic should know the XModel, but it doesn't
+ aModuleInfo.ModuleObject.set( mxDocModel, UNO_QUERY );
+ break;
+ case ApiModuleType::DOCUMENT:
+ aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "VBADocumentModule" ) );
+ // get the VBA object associated to the document module
+ if( rxDocObjectNA.is() ) try
+ {
+ aModuleInfo.ModuleObject.set( rxDocObjectNA->getByName( maName ), UNO_QUERY );
+ }
+ catch( Exception& )
+ {
+ }
+ break;
+ default:
+ aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "VBAUnknown" ) );
+ }
+ aSourceCode.append( sal_Unicode( '\n' ) );
+ if( mbExecutable )
+ {
+ aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Option VBASupport 1\n" ) );
+ if( mnType == ApiModuleType::CLASS )
+ aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Option ClassModule\n" ) );
+ }
+ else
+ {
+ // add a subroutine named after the module itself
+ aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Sub " ) ).
+ append( maName.replace( ' ', '_' ) ).append( sal_Unicode( '\n' ) );
+ }
+
+ // decompression starts at current stream position of aInStrm
+ VbaInputStream aVbaStrm( aInStrm );
+ // load the source code line-by-line, with some more processing
+ TextInputStream aVbaTextStrm( aVbaStrm, meTextEnc );
+ while( !aVbaTextStrm.isEof() )
+ {
+ OUString aCodeLine = aVbaTextStrm.readLine();
+ // skip all 'Attribute' statements
+ if( !aCodeLine.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( "Attribute " ) ) )
+ {
+ if( !mbExecutable )
+ aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Rem " ) );
+ aSourceCode.append( aCodeLine ).append( sal_Unicode( '\n' ) );
+ }
+ }
+
+ // close the subroutine named after the module
+ if( !mbExecutable )
+ aSourceCode.appendAscii( RTL_CONSTASCII_STRINGPARAM( "End Sub\n" ) );
+
+ // insert extended module info
+ try
+ {
+ Reference< XVBAModuleInfo > xVBAModuleInfo( rxBasicLib, UNO_QUERY_THROW );
+ xVBAModuleInfo->insertModuleInfo( maName, aModuleInfo );
+ }
+ catch( Exception& )
+ {
+ }
+
+ // insert the module into the passed Basic library
+ try
+ {
+ rxBasicLib->insertByName( maName, Any( aSourceCode.makeStringAndClear() ) );
+ }
+ catch( Exception& )
+ {
+ OSL_ENSURE( false, "VbaModule::importSourceCode - cannot insert module into library" );
+ }
+}
+
+// ============================================================================
+
+} // namespace ole
+} // namespace oox
diff --git a/oox/source/ole/vbaproject.cxx b/oox/source/ole/vbaproject.cxx
new file mode 100755
index 000000000000..a370fb3d168e
--- /dev/null
+++ b/oox/source/ole/vbaproject.cxx
@@ -0,0 +1,519 @@
+/*************************************************************************
+ *
+ * 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
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "oox/ole/vbaproject.hxx"
+#include <com/sun/star/document/XEventsSupplier.hpp>
+#include <com/sun/star/document/XStorageBasedDocument.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/script/ModuleType.hpp>
+#include <com/sun/star/script/XLibraryContainer.hpp>
+#include <com/sun/star/script/XVBACompat.hpp>
+#include <rtl/tencinfo.h>
+#include <rtl/ustrbuf.h>
+#include <comphelper/configurationhelper.hxx>
+#include <comphelper/string.hxx>
+#include "properties.hxx"
+#include "tokens.hxx"
+#include "oox/helper/binaryinputstream.hxx"
+#include "oox/helper/containerhelper.hxx"
+#include "oox/helper/propertyset.hxx"
+#include "oox/helper/textinputstream.hxx"
+#include "oox/ole/olestorage.hxx"
+#include "oox/ole/vbacontrol.hxx"
+#include "oox/ole/vbahelper.hxx"
+#include "oox/ole/vbainputstream.hxx"
+#include "oox/ole/vbamodule.hxx"
+
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+using ::com::sun::star::container::XNameAccess;
+using ::com::sun::star::container::XNameContainer;
+using ::com::sun::star::document::XEventsSupplier;
+using ::com::sun::star::document::XStorageBasedDocument;
+using ::com::sun::star::embed::XStorage;
+using ::com::sun::star::embed::XTransactedObject;
+using ::com::sun::star::frame::XModel;
+using ::com::sun::star::io::XStream;
+using ::com::sun::star::lang::XMultiServiceFactory;
+using ::com::sun::star::script::XLibraryContainer;
+using ::com::sun::star::script::XVBACompat;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Exception;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::uno::UNO_QUERY_THROW;
+using ::com::sun::star::uno::UNO_SET_THROW;
+using ::com::sun::star::uno::XInterface;
+using ::comphelper::ConfigurationHelper;
+
+namespace ApiModuleType = ::com::sun::star::script::ModuleType;
+
+namespace oox {
+namespace ole {
+
+// ============================================================================
+
+namespace {
+
+bool lclReadConfigItem( const Reference< XInterface >& rxConfigAccess, const OUString& rItemName )
+{
+ // some applications do not support all configuration items, assume 'false' in this case
+ try
+ {
+ Any aItem = ConfigurationHelper::readRelativeKey( rxConfigAccess, CREATE_OUSTRING( "Filter/Import/VBA" ), rItemName );
+ return aItem.has< bool >() && aItem.get< bool >();
+ }
+ catch( Exception& )
+ {
+ }
+ return false;
+}
+
+} // namespace
+
+// ----------------------------------------------------------------------------
+
+VbaFilterConfig::VbaFilterConfig( const Reference< XMultiServiceFactory >& rxGlobalFactory, const OUString& rConfigCompName )
+{
+ OSL_ENSURE( rxGlobalFactory.is(), "VbaFilterConfig::VbaFilterConfig - missing service factory" );
+ try
+ {
+ OSL_ENSURE( rConfigCompName.getLength() > 0, "VbaFilterConfig::VbaFilterConfig - invalid configuration component name" );
+ OUString aConfigPackage = CREATE_OUSTRING( "org.openoffice.Office." ) + rConfigCompName;
+ mxConfigAccess = ConfigurationHelper::openConfig( rxGlobalFactory, aConfigPackage, ConfigurationHelper::E_READONLY );
+ }
+ catch( Exception& )
+ {
+ }
+ OSL_ENSURE( mxConfigAccess.is(), "VbaFilterConfig::VbaFilterConfig - cannot open configuration" );
+}
+
+VbaFilterConfig::~VbaFilterConfig()
+{
+}
+
+bool VbaFilterConfig::isImportVba() const
+{
+ return lclReadConfigItem( mxConfigAccess, CREATE_OUSTRING( "Load" ) );
+}
+
+bool VbaFilterConfig::isImportVbaExecutable() const
+{
+ return lclReadConfigItem( mxConfigAccess, CREATE_OUSTRING( "Executable" ) );
+}
+
+bool VbaFilterConfig::isExportVba() const
+{
+ return lclReadConfigItem( mxConfigAccess, CREATE_OUSTRING( "Save" ) );
+}
+
+// ============================================================================
+
+VbaProject::VbaProject( const Reference< XMultiServiceFactory >& rxGlobalFactory,
+ const Reference< XModel >& rxDocModel, const OUString& rConfigCompName ) :
+ VbaFilterConfig( rxGlobalFactory, rConfigCompName ),
+ mxGlobalFactory( rxGlobalFactory ),
+ mxDocModel( rxDocModel ),
+ maLibName( CREATE_OUSTRING( "Standard" ) )
+{
+ OSL_ENSURE( mxDocModel.is(), "VbaProject::VbaProject - missing document model" );
+ mxBasicLib = openLibrary( PROP_BasicLibraries, false );
+ mxDialogLib = openLibrary( PROP_DialogLibraries, false );
+}
+
+VbaProject::~VbaProject()
+{
+}
+
+void VbaProject::importVbaProject( StorageBase& rVbaPrjStrg, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr )
+{
+ if( rVbaPrjStrg.isStorage() )
+ {
+ // load the code modules and forms
+ if( isImportVba() )
+ importVba( rVbaPrjStrg, rGraphicHelper, bDefaultColorBgr );
+ // copy entire storage into model
+ if( isExportVba() )
+ copyStorage( rVbaPrjStrg );
+ }
+}
+
+bool VbaProject::hasModules() const
+{
+ return mxBasicLib.is() && mxBasicLib->hasElements();
+}
+
+bool VbaProject::hasModule( const OUString& rModuleName ) const
+{
+ return mxBasicLib.is() && mxBasicLib->hasByName( rModuleName );
+}
+
+bool VbaProject::hasDialogs() const
+{
+ return mxDialogLib.is() && mxDialogLib->hasElements();
+}
+
+bool VbaProject::hasDialog( const OUString& rDialogName ) const
+{
+ return mxDialogLib.is() && mxDialogLib->hasByName( rDialogName );
+}
+
+// Insert VBA code modules and VBA macros into modules ------------------------
+
+bool VbaProject::insertMacro( const OUString& rModuleName,
+ const OUString& rMacroName, const OUString& rMacroArgs,
+ const OUString& rMacroType, const OUString& rMacroCode )
+{
+ return
+ // do nothing if macros are imported as comments
+ isImportVbaExecutable() &&
+ // try to insert the macro (will check that the macro does not exist yet)
+ VbaHelper::insertMacro( mxBasicLib, rModuleName, rMacroName, rMacroArgs, rMacroType, rMacroCode );
+}
+
+// Attach VBA macros to generic or document events ----------------------------
+
+bool VbaProject::attachMacroToEvent( const Reference< XEventsSupplier >& rxEventsSupp,
+ const OUString& rEventName, const OUString& rModuleName, const OUString& rMacroName )
+{
+ return
+ // do not attach if macros are imported as comments
+ isImportVbaExecutable() &&
+ // check that the specified macro exists in the module
+ VbaHelper::hasMacro( mxBasicLib, rModuleName, rMacroName ) &&
+ // attach the macro to the events supplier
+ VbaHelper::attachMacroToEvent( rxEventsSupp, rEventName, maLibName, rModuleName, rMacroName );
+}
+
+bool VbaProject::attachMacroToDocumentEvent( const OUString& rEventName,
+ const OUString& rModuleName, const OUString& rMacroName )
+{
+ Reference< XEventsSupplier > xEventsSupp( mxDocModel, UNO_QUERY );
+ return attachMacroToEvent( xEventsSupp, rEventName, rModuleName, rMacroName );
+}
+
+bool VbaProject::attachMacroToEvent( const Reference< XEventsSupplier >& rxEventsSupp,
+ const OUString& rEventName, const OUString& rModuleName, const OUString& rMacroName,
+ const OUString& rProxyArgs, const OUString& rProxyType, const OUString& rProxyCode )
+{
+ // receive module source code, and check that the specified macro exists in the module
+ OUString aSourceCode = VbaHelper::getSourceCode( mxBasicLib, rModuleName );
+ if( isImportVbaExecutable() && VbaHelper::hasMacro( aSourceCode, rMacroName ) )
+ {
+ // create the name of the proxy macro, and the macro source code
+ OUString aProxyName = OUStringBuffer( rMacroName ).append( sal_Unicode( '_' ) ).
+ append( rEventName ).appendAscii( "_Proxy" ).makeStringAndClear();
+ // replace $MACRO and $PROXY placeholders in proxy source code
+ OUString aProxyCode = ::comphelper::string::searchAndReplaceAsciiL( rProxyCode, RTL_CONSTASCII_STRINGPARAM( "$MACRO" ), rMacroName );
+ aProxyCode = ::comphelper::string::searchAndReplaceAsciiL( aProxyCode, RTL_CONSTASCII_STRINGPARAM( "$PROXY" ), aProxyName );
+ // insert the new macro into the code module and attach it to the event
+ return
+ VbaHelper::insertMacro( mxBasicLib, rModuleName, aProxyName, rProxyArgs, rProxyType, aProxyCode ) &&
+ VbaHelper::attachMacroToEvent( rxEventsSupp, rEventName, maLibName, rModuleName, aProxyName );
+ }
+ return false;
+}
+
+bool VbaProject::attachMacroToDocumentEvent(
+ const OUString& rEventName, const OUString& rModuleName, const OUString& rMacroName,
+ const OUString& rProxyArgs, const OUString& rProxyType, const OUString& rProxyCode )
+{
+ Reference< XEventsSupplier > xEventsSupp( mxDocModel, UNO_QUERY );
+ return attachMacroToEvent( xEventsSupp, rEventName, rModuleName, rMacroName, rProxyArgs, rProxyType, rProxyCode );
+}
+
+// private --------------------------------------------------------------------
+
+Reference< XLibraryContainer > VbaProject::getLibraryContainer( sal_Int32 nPropId )
+{
+ PropertySet aDocProp( mxDocModel );
+ Reference< XLibraryContainer > xLibContainer( aDocProp.getAnyProperty( nPropId ), UNO_QUERY );
+ return xLibContainer;
+}
+
+Reference< XNameContainer > VbaProject::openLibrary( sal_Int32 nPropId, bool bCreateMissing )
+{
+ Reference< XNameContainer > xLibrary;
+ try
+ {
+ Reference< XLibraryContainer > xLibContainer( getLibraryContainer( nPropId ), UNO_SET_THROW );
+ if( bCreateMissing && !xLibContainer->hasByName( maLibName ) )
+ xLibContainer->createLibrary( maLibName );
+ xLibrary.set( xLibContainer->getByName( maLibName ), UNO_QUERY_THROW );
+ }
+ catch( Exception& )
+ {
+ }
+ OSL_ENSURE( !bCreateMissing || xLibrary.is(), "VbaProject::openLibrary - cannot create library" );
+ return xLibrary;
+}
+
+Reference< XNameContainer > VbaProject::createBasicLibrary()
+{
+ if( !mxBasicLib.is() )
+ mxBasicLib = openLibrary( PROP_BasicLibraries, true );
+ return mxBasicLib;
+}
+
+Reference< XNameContainer > VbaProject::createDialogLibrary()
+{
+ if( !mxDialogLib.is() )
+ mxDialogLib = openLibrary( PROP_DialogLibraries, true );
+ return mxDialogLib;
+}
+
+void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr )
+{
+ StorageRef xVbaStrg = rVbaPrjStrg.openSubStorage( CREATE_OUSTRING( "VBA" ), false );
+ OSL_ENSURE( xVbaStrg.get(), "VbaProject::importVba - cannot open 'VBA' substorage" );
+ if( !xVbaStrg )
+ return;
+
+ /* Read the 'VBA/dir' stream which contains general settings of the VBA
+ project such as the text encoding used throughout several streams, and
+ a list of all code modules.
+ */
+ BinaryXInputStream aInStrm( xVbaStrg->openInputStream( CREATE_OUSTRING( "dir" ) ), true );
+ // VbaInputStream implements decompression
+ VbaInputStream aDirStrm( aInStrm );
+ OSL_ENSURE( !aDirStrm.isEof(), "VbaProject::importVba - cannot open 'dir' stream" );
+ if( aDirStrm.isEof() )
+ return;
+
+ // read all records of the directory
+ rtl_TextEncoding eTextEnc = RTL_TEXTENCODING_MS_1252;
+ sal_uInt16 nModuleCount = 0;
+ bool bExecutable = isImportVbaExecutable();
+
+ typedef RefMap< OUString, VbaModule > VbaModuleMap;
+ VbaModuleMap aModules, aModulesByStrm;
+
+ sal_uInt16 nRecId = 0;
+ StreamDataSequence aRecData;
+ while( VbaHelper::readDirRecord( nRecId, aRecData, aDirStrm ) && (nRecId != VBA_ID_PROJECTEND) )
+ {
+ // create record stream object from imported record data
+ SequenceInputStream aRecStrm( aRecData );
+ sal_Int32 nRecSize = aRecData.getLength();
+ switch( nRecId )
+ {
+#define OOX_ENSURE_RECORDSIZE( cond ) OSL_ENSURE( cond, "VbaProject::importVba - invalid record size" )
+ case VBA_ID_PROJECTCODEPAGE:
+ {
+ OOX_ENSURE_RECORDSIZE( nRecSize == 2 );
+ OSL_ENSURE( aModules.empty(), "VbaProject::importVba - unexpected PROJECTCODEPAGE record" );
+ rtl_TextEncoding eNewTextEnc = rtl_getTextEncodingFromWindowsCodePage( aRecStrm.readuInt16() );
+ OSL_ENSURE( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW, "VbaProject::importVba - unknown text encoding" );
+ if( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW )
+ eTextEnc = eNewTextEnc;
+ }
+ break;
+ case VBA_ID_PROJECTMODULES:
+ OOX_ENSURE_RECORDSIZE( nRecSize == 2 );
+ OSL_ENSURE( aModules.empty(), "VbaProject::importVba - unexpected PROJECTMODULES record" );
+ aRecStrm >> nModuleCount;
+ break;
+ case VBA_ID_MODULENAME:
+ {
+ OUString aName = aRecStrm.readCharArrayUC( nRecSize, eTextEnc );
+ OSL_ENSURE( aName.getLength() > 0, "VbaProject::importVba - invalid module name" );
+ OSL_ENSURE( !aModules.has( aName ), "VbaProject::importVba - multiple modules with the same name" );
+ VbaModuleMap::mapped_type& rxModule = aModules[ aName ];
+ rxModule.reset( new VbaModule( mxDocModel, aName, eTextEnc, bExecutable ) );
+ // read all remaining records until the MODULEEND record
+ rxModule->importDirRecords( aDirStrm );
+ OSL_ENSURE( !aModulesByStrm.has( rxModule->getStreamName() ), "VbaProject::importVba - multiple modules with the same stream name" );
+ aModulesByStrm[ rxModule->getStreamName() ] = rxModule;
+ }
+ break;
+#undef OOX_ENSURE_RECORDSIZE
+ }
+ }
+ OSL_ENSURE( nModuleCount == aModules.size(), "VbaProject::importVba - invalid module count" );
+
+ /* The directory does not contain the real type of the modules, it
+ distinguishes only between 'procedural' and 'document' (the latter
+ includes class and form modules). Now, the exact type of all modules
+ will be read from the 'PROJECT' stream. It consists of text lines in
+ 'key=value' format which list the code modules by type.
+
+ - The line 'document=<modulename>/&HXXXXXXXX' declares document
+ modules. These are attached to the Word document (usually called
+ 'ThisDocument'), the Excel workbook (usually called
+ 'ThisWorkbook'), or single Excel worksheets or chartsheets (usually
+ called 'SheetX' or 'ChartX', X being a decimal number). Of course,
+ users may rename all these modules. The slash character separates
+ an automation server version number (hexadecimal 'XXXXXXXX') from
+ the module name.
+ - The line 'Module=<modulename>' declares common procedural code
+ modules.
+ - The line 'Class=<modulename>' declares a class module.
+ - The line 'BaseClass=<modulename>' declares a code module attached
+ to a user form with the same name.
+ */
+ BinaryXInputStream aPrjStrm( rVbaPrjStrg.openInputStream( CREATE_OUSTRING( "PROJECT" ) ), true );
+ OSL_ENSURE( !aPrjStrm.isEof(), "VbaProject::importVba - cannot open 'PROJECT' stream" );
+ // do not exit if this stream does not exist, but proceed to load the modules below
+ if( !aPrjStrm.isEof() )
+ {
+ TextInputStream aPrjTextStrm( aPrjStrm, eTextEnc );
+ OUString aKey, aValue;
+ bool bExitLoop = false;
+ while( !bExitLoop && !aPrjTextStrm.isEof() )
+ {
+ // read a text line from the stream
+ OUString aLine = aPrjTextStrm.readLine().trim();
+ sal_Int32 nLineLen = aLine.getLength();
+ // exit if a subsection starts (section name is given in brackets)
+ bExitLoop = (nLineLen >= 2) && (aLine[ 0 ] == '[') && (aLine[ nLineLen - 1 ] == ']');
+ if( !bExitLoop && VbaHelper::extractKeyValue( aKey, aValue, aLine ) )
+ {
+ sal_Int32 nType = ApiModuleType::UNKNOWN;
+ if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "Document" ) ) )
+ {
+ nType = ApiModuleType::DOCUMENT;
+ // strip automation server version from module names
+ sal_Int32 nSlashPos = aValue.indexOf( '/' );
+ if( nSlashPos >= 0 )
+ aValue = aValue.copy( 0, nSlashPos );
+ }
+ else if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "Module" ) ) )
+ nType = ApiModuleType::NORMAL;
+ else if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "Class" ) ) )
+ nType = ApiModuleType::CLASS;
+ else if( aKey.equalsIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "BaseClass" ) ) )
+ nType = ApiModuleType::FORM;
+
+ if( (nType != ApiModuleType::UNKNOWN) && (aValue.getLength() > 0) )
+ {
+ OSL_ENSURE( aModules.has( aValue ), "VbaProject::importVba - module not found" );
+ if( VbaModule* pModule = aModules.get( aValue ).get() )
+ pModule->setType( nType );
+ }
+ }
+ }
+ }
+
+ /* Now it is time to load the source code. All modules will be inserted
+ into the Basic library of the document specified by the 'maLibName'
+ member. Do not create the Basic library, if there are no modules
+ specified. */
+ if( !aModules.empty() ) try
+ {
+ // get the basic library
+ Reference< XNameContainer > xBasicLib( createBasicLibrary(), UNO_SET_THROW );
+
+ // set library container to VBA compatibility mode
+ try
+ {
+ Reference< XVBACompat >( getLibraryContainer( PROP_BasicLibraries ), UNO_QUERY_THROW )->setVBACompatModeOn( sal_True );
+ }
+ catch( Exception& )
+ {
+ }
+
+ // try to get access to document objects related to code modules
+ Reference< XNameAccess > xDocObjectNA;
+ try
+ {
+ Reference< XMultiServiceFactory > xModelFactory( mxDocModel, UNO_QUERY_THROW );
+ xDocObjectNA.set( xModelFactory->createInstance( CREATE_OUSTRING( "ooo.vba.VBAObjectModuleObjectProvider" ) ), UNO_QUERY );
+ }
+ catch( Exception& )
+ {
+ // not all documents support this
+ }
+
+ // call Basic source code import for each module, boost::[c]ref enforces pass-by-ref
+ if( xBasicLib.is() )
+ aModules.forEachMem( &VbaModule::importSourceCode,
+ ::boost::ref( *xVbaStrg ), ::boost::cref( xBasicLib ), ::boost::cref( xDocObjectNA ) );
+ }
+ catch( Exception& )
+ {
+ }
+
+ /* Load the forms. The file format specification requires that a module
+ must exist for every form. We are a bit more tolerant and scan the
+ project storage for all form substorages. This may 'repair' broken VBA
+ storages that misses to mention a module for an existing form. */
+ ::std::vector< OUString > aElements;
+ rVbaPrjStrg.getElementNames( aElements );
+ for( ::std::vector< OUString >::iterator aIt = aElements.begin(), aEnd = aElements.end(); aIt != aEnd; ++aIt )
+ {
+ // try to open the element as storage
+ if( !aIt->equals( CREATE_OUSTRING( "VBA" ) ) )
+ {
+ StorageRef xSubStrg = rVbaPrjStrg.openSubStorage( *aIt, false );
+ if( xSubStrg.get() ) try
+ {
+ // resolve module name from storage name (which equals the module stream name)
+ VbaModule* pModule = aModulesByStrm.get( *aIt ).get();
+ OSL_ENSURE( pModule && (pModule->getType() == ApiModuleType::FORM),
+ "VbaProject::importVba - form substorage without form module" );
+ OUString aModuleName;
+ if( pModule )
+ aModuleName = pModule->getName();
+
+ // create and import the form
+ Reference< XNameContainer > xDialogLib( createDialogLibrary(), UNO_SET_THROW );
+ VbaUserForm aForm( mxGlobalFactory, rGraphicHelper, bDefaultColorBgr );
+ aForm.importForm( xDialogLib, *xSubStrg, aModuleName, eTextEnc );
+ }
+ catch( Exception& )
+ {
+ }
+ }
+ }
+}
+
+void VbaProject::copyStorage( StorageBase& rVbaPrjStrg )
+{
+ try
+ {
+ Reference< XStorageBasedDocument > xStorageBasedDoc( mxDocModel, UNO_QUERY_THROW );
+ Reference< XStorage > xDocStorage( xStorageBasedDoc->getDocumentStorage(), UNO_QUERY_THROW );
+ {
+ using namespace ::com::sun::star::embed::ElementModes;
+ Reference< XStream > xDocStream( xDocStorage->openStreamElement( CREATE_OUSTRING( "_MS_VBA_Macros" ), SEEKABLE | WRITE | TRUNCATE ), UNO_SET_THROW );
+ OleStorage aDestStorage( mxGlobalFactory, xDocStream, false );
+ rVbaPrjStrg.copyStorageToStorage( aDestStorage );
+ aDestStorage.commit();
+ }
+ Reference< XTransactedObject >( xDocStorage, UNO_QUERY_THROW )->commit();
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+// ============================================================================
+
+} // namespace ole
+} // namespace oox