Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "oox/ole/olehelper.hxx"
21 :
22 : #include <rtl/ustrbuf.hxx>
23 : #include "oox/helper/binaryinputstream.hxx"
24 : #include "oox/helper/graphichelper.hxx"
25 : #include "oox/token/tokens.hxx"
26 : #include "oox/ole/axcontrol.hxx"
27 : #include "oox/helper/propertymap.hxx"
28 : #include "oox/helper/propertyset.hxx"
29 : #include "oox/ole/olestorage.hxx"
30 :
31 : #include <com/sun/star/beans/XPropertySet.hpp>
32 : #include <com/sun/star/form/FormComponentType.hpp>
33 : #include <com/sun/star/form/XFormsSupplier.hpp>
34 : #include <com/sun/star/form/XForm.hpp>
35 : #include <com/sun/star/lang/XServiceInfo.hpp>
36 : #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
37 : #include <com/sun/star/container/XNameContainer.hpp>
38 : #include <com/sun/star/awt/Size.hpp>
39 :
40 : #include <tools/globname.hxx>
41 : #include <unotools/streamwrap.hxx>
42 : #include <comphelper/processfactory.hxx>
43 :
44 : namespace oox {
45 : namespace ole {
46 :
47 : // ============================================================================
48 :
49 : using ::com::sun::star::form::XFormComponent;
50 : using ::com::sun::star::form::XForm;
51 : using ::com::sun::star::awt::XControlModel;
52 : using ::com::sun::star::awt::Size;
53 : using ::com::sun::star::frame::XModel;
54 : using ::com::sun::star::form::XFormsSupplier;
55 : using ::com::sun::star::drawing::XDrawPage;
56 : using ::com::sun::star::drawing::XDrawPageSupplier;
57 : using ::com::sun::star::drawing::XShapes;
58 : using ::com::sun::star::io::XOutputStream;
59 : using ::com::sun::star::io::XInputStream;
60 : using ::com::sun::star::beans::XPropertySet;
61 : using ::com::sun::star::uno::Reference;
62 : using ::com::sun::star::uno::XInterface;
63 : using ::com::sun::star::uno::UNO_QUERY;
64 : using ::com::sun::star::uno::Any;
65 : using ::com::sun::star::uno::XComponentContext;
66 : using ::com::sun::star::container::XIndexContainer;
67 : using ::com::sun::star::container::XNameContainer;
68 : using ::com::sun::star::lang::XMultiServiceFactory;
69 : using ::com::sun::star::lang::XServiceInfo;
70 :
71 : using namespace ::com::sun::star::form;
72 :
73 : // ============================================================================
74 :
75 : namespace {
76 :
77 : const sal_uInt32 OLE_COLORTYPE_MASK = 0xFF000000;
78 : const sal_uInt32 OLE_COLORTYPE_CLIENT = 0x00000000;
79 : const sal_uInt32 OLE_COLORTYPE_PALETTE = 0x01000000;
80 : const sal_uInt32 OLE_COLORTYPE_BGR = 0x02000000;
81 : const sal_uInt32 OLE_COLORTYPE_SYSCOLOR = 0x80000000;
82 :
83 : const sal_uInt32 OLE_PALETTECOLOR_MASK = 0x0000FFFF;
84 : const sal_uInt32 OLE_BGRCOLOR_MASK = 0x00FFFFFF;
85 : const sal_uInt32 OLE_SYSTEMCOLOR_MASK = 0x0000FFFF;
86 :
87 :
88 : /** Swaps the red and blue component of the passed color. */
89 3 : inline sal_uInt32 lclSwapRedBlue( sal_uInt32 nColor )
90 : {
91 3 : return static_cast< sal_uInt32 >( (nColor & 0xFF00FF00) | ((nColor & 0x0000FF) << 16) | ((nColor & 0xFF0000) >> 16) );
92 : }
93 :
94 : /** Returns the UNO RGB color from the passed encoded OLE BGR color. */
95 2 : inline sal_Int32 lclDecodeBgrColor( sal_uInt32 nOleColor )
96 : {
97 2 : return static_cast< sal_Int32 >( lclSwapRedBlue( nOleColor ) & 0xFFFFFF );
98 : }
99 :
100 : // ----------------------------------------------------------------------------
101 :
102 : const sal_Char OLE_GUID_URLMONIKER[] = "{79EAC9E0-BAF9-11CE-8C82-00AA004BA90B}";
103 : const sal_Char OLE_GUID_FILEMONIKER[] = "{00000303-0000-0000-C000-000000000046}";
104 :
105 : const sal_uInt32 OLE_STDPIC_ID = 0x0000746C;
106 :
107 : const sal_uInt32 OLE_STDHLINK_VERSION = 2;
108 : const sal_uInt32 OLE_STDHLINK_HASTARGET = 0x00000001; /// Has hyperlink moniker.
109 : const sal_uInt32 OLE_STDHLINK_ABSOLUTE = 0x00000002; /// Absolute path.
110 : const sal_uInt32 OLE_STDHLINK_HASLOCATION = 0x00000008; /// Has target location.
111 : const sal_uInt32 OLE_STDHLINK_HASDISPLAY = 0x00000010; /// Has display string.
112 : const sal_uInt32 OLE_STDHLINK_HASGUID = 0x00000020; /// Has identification GUID.
113 : const sal_uInt32 OLE_STDHLINK_HASTIME = 0x00000040; /// Has creation time.
114 : const sal_uInt32 OLE_STDHLINK_HASFRAME = 0x00000080; /// Has frame.
115 : const sal_uInt32 OLE_STDHLINK_ASSTRING = 0x00000100; /// Hyperlink as simple string.
116 :
117 : struct GUIDCNamePair
118 : {
119 : const char* sGUID;
120 : const char* sName;
121 : };
122 :
123 : struct IdCntrlData
124 : {
125 : sal_Int16 nId;
126 : GUIDCNamePair aData;
127 : };
128 :
129 : const sal_Int16 TOGGLEBUTTON = -1;
130 : const sal_Int16 FORMULAFIELD = -2;
131 :
132 : typedef std::map< sal_Int16, GUIDCNamePair > GUIDCNamePairMap;
133 1 : class classIdToGUIDCNamePairMap
134 : {
135 : GUIDCNamePairMap mnIdToGUIDCNamePairMap;
136 : classIdToGUIDCNamePairMap();
137 : public:
138 : static GUIDCNamePairMap& get();
139 : };
140 :
141 1 : classIdToGUIDCNamePairMap::classIdToGUIDCNamePairMap()
142 : {
143 : IdCntrlData initialCntrlData[] =
144 : {
145 : // Command button MUST be at index 0
146 : { FormComponentType::COMMANDBUTTON,
147 : { AX_GUID_COMMANDBUTTON, "CommandButton"} ,
148 : },
149 : // Toggle button MUST be at index 1
150 : { TOGGLEBUTTON,
151 : { AX_GUID_TOGGLEBUTTON, "ToggleButton"},
152 : },
153 : { FormComponentType::FIXEDTEXT,
154 : { AX_GUID_LABEL, "Label"},
155 : },
156 : { FormComponentType::TEXTFIELD,
157 : { AX_GUID_TEXTBOX, "TextBox"},
158 : },
159 : { FormComponentType::LISTBOX,
160 : { AX_GUID_LISTBOX, "ListBox"},
161 : },
162 : { FormComponentType::COMBOBOX,
163 : { AX_GUID_COMBOBOX, "ComboBox"},
164 : },
165 : { FormComponentType::CHECKBOX,
166 : { AX_GUID_CHECKBOX, "CheckBox"},
167 : },
168 : { FormComponentType::RADIOBUTTON,
169 : { AX_GUID_OPTIONBUTTON, "OptionButton"},
170 : },
171 : { FormComponentType::IMAGECONTROL,
172 : { AX_GUID_IMAGE, "Image"},
173 : },
174 : { FormComponentType::DATEFIELD,
175 : { AX_GUID_TEXTBOX, "TextBox"},
176 : },
177 : { FormComponentType::TIMEFIELD,
178 : { AX_GUID_TEXTBOX, "TextBox"},
179 : },
180 : { FormComponentType::NUMERICFIELD,
181 : { AX_GUID_TEXTBOX, "TextBox"},
182 : },
183 : { FormComponentType::CURRENCYFIELD,
184 : { AX_GUID_TEXTBOX, "TextBox"},
185 : },
186 : { FormComponentType::PATTERNFIELD,
187 : { AX_GUID_TEXTBOX, "TextBox"},
188 : },
189 : { FORMULAFIELD,
190 : { AX_GUID_TEXTBOX, "TextBox"},
191 : },
192 : { FormComponentType::IMAGEBUTTON,
193 : { AX_GUID_COMMANDBUTTON, "CommandButton"},
194 : },
195 : { FormComponentType::SPINBUTTON,
196 : { AX_GUID_SPINBUTTON, "SpinButton"},
197 : },
198 : { FormComponentType::SCROLLBAR,
199 : { AX_GUID_SCROLLBAR, "ScrollBar"},
200 : }
201 1 : };
202 1 : int length = SAL_N_ELEMENTS( initialCntrlData );
203 1 : IdCntrlData* pData = initialCntrlData;
204 19 : for ( int index = 0; index < length; ++index, ++pData )
205 18 : mnIdToGUIDCNamePairMap[ pData->nId ] = pData->aData;
206 1 : };
207 :
208 1 : GUIDCNamePairMap& classIdToGUIDCNamePairMap::get()
209 : {
210 1 : static classIdToGUIDCNamePairMap theInst;
211 1 : return theInst.mnIdToGUIDCNamePairMap;
212 : }
213 :
214 : // ----------------------------------------------------------------------------
215 :
216 : template< typename Type >
217 484 : void lclAppendHex( OUStringBuffer& orBuffer, Type nValue )
218 : {
219 484 : const sal_Int32 nWidth = 2 * sizeof( Type );
220 : static const sal_Unicode spcHexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
221 484 : orBuffer.setLength( orBuffer.getLength() + nWidth );
222 1892 : for( sal_Int32 nCharIdx = orBuffer.getLength() - 1, nCharEnd = nCharIdx - nWidth; nCharIdx > nCharEnd; --nCharIdx, nValue >>= 4 )
223 1408 : orBuffer[nCharIdx] = spcHexChars[ nValue & 0xF ];
224 484 : }
225 :
226 : } // namespace
227 :
228 : // ============================================================================
229 :
230 0 : StdFontInfo::StdFontInfo() :
231 : mnHeight( 0 ),
232 : mnWeight( OLE_STDFONT_NORMAL ),
233 : mnCharSet( WINDOWS_CHARSET_ANSI ),
234 0 : mnFlags( 0 )
235 : {
236 0 : }
237 :
238 0 : StdFontInfo::StdFontInfo( const OUString& rName, sal_uInt32 nHeight,
239 : sal_uInt16 nWeight, sal_uInt16 nCharSet, sal_uInt8 nFlags ) :
240 : maName( rName ),
241 : mnHeight( nHeight ),
242 : mnWeight( nWeight ),
243 : mnCharSet( nCharSet ),
244 0 : mnFlags( nFlags )
245 : {
246 0 : }
247 :
248 : // ============================================================================
249 :
250 84 : sal_Int32 OleHelper::decodeOleColor(
251 : const GraphicHelper& rGraphicHelper, sal_uInt32 nOleColor, bool bDefaultColorBgr )
252 : {
253 : static const sal_Int32 spnSystemColors[] =
254 : {
255 : XML_scrollBar, XML_background, XML_activeCaption, XML_inactiveCaption,
256 : XML_menu, XML_window, XML_windowFrame, XML_menuText,
257 : XML_windowText, XML_captionText, XML_activeBorder, XML_inactiveBorder,
258 : XML_appWorkspace, XML_highlight, XML_highlightText, XML_btnFace,
259 : XML_btnShadow, XML_grayText, XML_btnText, XML_inactiveCaptionText,
260 : XML_btnHighlight, XML_3dDkShadow, XML_3dLight, XML_infoText,
261 : XML_infoBk
262 : };
263 :
264 84 : switch( nOleColor & OLE_COLORTYPE_MASK )
265 : {
266 : case OLE_COLORTYPE_CLIENT:
267 1 : return bDefaultColorBgr ? lclDecodeBgrColor( nOleColor ) : rGraphicHelper.getPaletteColor( nOleColor & OLE_PALETTECOLOR_MASK );
268 :
269 : case OLE_COLORTYPE_PALETTE:
270 0 : return rGraphicHelper.getPaletteColor( nOleColor & OLE_PALETTECOLOR_MASK );
271 :
272 : case OLE_COLORTYPE_BGR:
273 1 : return lclDecodeBgrColor( nOleColor );
274 :
275 : case OLE_COLORTYPE_SYSCOLOR:
276 82 : return rGraphicHelper.getSystemColor( STATIC_ARRAY_SELECT( spnSystemColors, nOleColor & OLE_SYSTEMCOLOR_MASK, XML_TOKEN_INVALID ), API_RGB_WHITE );
277 : }
278 : OSL_FAIL( "OleHelper::decodeOleColor - unknown color type" );
279 0 : return API_RGB_BLACK;
280 : }
281 :
282 1 : sal_uInt32 OleHelper::encodeOleColor( sal_Int32 nRgbColor )
283 : {
284 1 : return OLE_COLORTYPE_BGR | lclSwapRedBlue( static_cast< sal_uInt32 >( nRgbColor & 0xFFFFFF ) );
285 : }
286 :
287 0 : void OleHelper::exportGuid( BinaryOutputStream& rOStr, const SvGlobalName& rId )
288 : {
289 0 : const sal_uInt8* pBytes = rId.GetBytes();
290 : sal_uInt32 a;
291 0 : memcpy(&a, pBytes, sizeof(sal_uInt32));
292 0 : rOStr<< a;
293 :
294 : sal_uInt16 b;
295 0 : memcpy(&b, pBytes+4, sizeof(sal_uInt16));
296 0 : rOStr << b;
297 :
298 0 : memcpy(&b, pBytes+6, sizeof(sal_uInt16));
299 0 : rOStr << b;
300 :
301 0 : rOStr.writeArray( (sal_uInt8 *)&pBytes[ 8 ], 8 );
302 0 : }
303 44 : OUString OleHelper::importGuid( BinaryInputStream& rInStrm )
304 : {
305 44 : OUStringBuffer aBuffer;
306 44 : aBuffer.append( sal_Unicode( '{' ) );
307 44 : lclAppendHex( aBuffer, rInStrm.readuInt32() );
308 44 : aBuffer.append( sal_Unicode( '-' ) );
309 44 : lclAppendHex( aBuffer, rInStrm.readuInt16() );
310 44 : aBuffer.append( sal_Unicode( '-' ) );
311 44 : lclAppendHex( aBuffer, rInStrm.readuInt16() );
312 44 : aBuffer.append( sal_Unicode( '-' ) );
313 44 : lclAppendHex( aBuffer, rInStrm.readuInt8() );
314 44 : lclAppendHex( aBuffer, rInStrm.readuInt8() );
315 44 : aBuffer.append( sal_Unicode( '-' ) );
316 308 : for( int nIndex = 0; nIndex < 6; ++nIndex )
317 264 : lclAppendHex( aBuffer, rInStrm.readuInt8() );
318 44 : aBuffer.append( sal_Unicode( '}' ) );
319 44 : return aBuffer.makeStringAndClear();
320 : }
321 :
322 0 : bool OleHelper::importStdFont( StdFontInfo& orFontInfo, BinaryInputStream& rInStrm, bool bWithGuid )
323 : {
324 0 : if( bWithGuid )
325 : {
326 0 : bool bIsStdFont = importGuid( rInStrm ) == OLE_GUID_STDFONT;
327 : OSL_ENSURE( bIsStdFont, "OleHelper::importStdFont - unexpected header GUID, expected StdFont" );
328 0 : if( !bIsStdFont )
329 0 : return false;
330 : }
331 :
332 : sal_uInt8 nVersion, nNameLen;
333 0 : rInStrm >> nVersion >> orFontInfo.mnCharSet >> orFontInfo.mnFlags >> orFontInfo.mnWeight >> orFontInfo.mnHeight >> nNameLen;
334 : // according to spec the name is ASCII
335 0 : orFontInfo.maName = rInStrm.readCharArrayUC( nNameLen, RTL_TEXTENCODING_ASCII_US );
336 : OSL_ENSURE( nVersion <= 1, "OleHelper::importStdFont - wrong version" );
337 0 : return !rInStrm.isEof() && (nVersion <= 1);
338 : }
339 :
340 0 : bool OleHelper::importStdPic( StreamDataSequence& orGraphicData, BinaryInputStream& rInStrm, bool bWithGuid )
341 : {
342 0 : if( bWithGuid )
343 : {
344 0 : bool bIsStdPic = importGuid( rInStrm ) == OLE_GUID_STDPIC;
345 : OSL_ENSURE( bIsStdPic, "OleHelper::importStdPic - unexpected header GUID, expected StdPic" );
346 0 : if( !bIsStdPic )
347 0 : return false;
348 : }
349 :
350 : sal_uInt32 nStdPicId;
351 : sal_Int32 nBytes;
352 0 : rInStrm >> nStdPicId >> nBytes;
353 : OSL_ENSURE( nStdPicId == OLE_STDPIC_ID, "OleHelper::importStdPic - unexpected header version" );
354 0 : return !rInStrm.isEof() && (nStdPicId == OLE_STDPIC_ID) && (nBytes > 0) && (rInStrm.readData( orGraphicData, nBytes ) == nBytes);
355 : }
356 :
357 : Reference< ::com::sun::star::frame::XFrame >
358 154 : lcl_getFrame( const Reference< ::com::sun::star::frame::XModel >& rxModel )
359 : {
360 154 : Reference< ::com::sun::star::frame::XFrame > xFrame;
361 154 : if ( rxModel.is() )
362 : {
363 154 : Reference< ::com::sun::star::frame::XController > xController = rxModel->getCurrentController();
364 154 : xFrame = xController.is() ? xController->getFrame() : NULL;
365 : }
366 154 : return xFrame;
367 : }
368 :
369 : class OleFormCtrlExportHelper
370 : {
371 : ::oox::ole::EmbeddedControl maControl;
372 : ::oox::ole::ControlModelBase* mpModel;
373 : ::oox::GraphicHelper maGrfHelper;
374 : Reference< XModel > mxDocModel;
375 : Reference< XControlModel > mxControlModel;
376 :
377 : OUString maName;
378 : OUString maTypeName;
379 : OUString maFullName;
380 : OUString maGUID;
381 : public:
382 : OleFormCtrlExportHelper( const Reference< XComponentContext >& rxCtx, const Reference< XModel >& xDocModel, const Reference< XControlModel >& xModel );
383 1 : virtual ~OleFormCtrlExportHelper() { }
384 1 : virtual OUString getGUID()
385 : {
386 1 : OUString sResult;
387 1 : if ( maGUID.getLength() > 2 )
388 1 : sResult = maGUID.copy(1, maGUID.getLength() - 2 );
389 1 : return sResult;
390 : }
391 1 : OUString getFullName() { return maFullName; }
392 1 : OUString getTypeName() { return maTypeName; }
393 1 : bool isValid() { return mpModel != NULL; }
394 : void exportName( const Reference< XOutputStream >& rxOut );
395 : void exportCompObj( const Reference< XOutputStream >& rxOut );
396 : void exportControl( const Reference< XOutputStream >& rxOut, const ::com::sun::star::awt::Size& rSize );
397 : };
398 1 : OleFormCtrlExportHelper::OleFormCtrlExportHelper( const Reference< XComponentContext >& rxCtx, const Reference< XModel >& rxDocModel, const Reference< XControlModel >& xCntrlModel ) : maControl( "Unknown" ), mpModel( NULL ), maGrfHelper( rxCtx, lcl_getFrame( rxDocModel ), StorageRef() ), mxDocModel( rxDocModel ), mxControlModel( xCntrlModel )
399 : {
400 : // try to get the guid
401 1 : Reference< com::sun::star::beans::XPropertySet > xProps( xCntrlModel, UNO_QUERY );
402 1 : if ( xProps.is() )
403 : {
404 1 : sal_Int16 nClassId = 0;
405 1 : PropertySet aPropSet( mxControlModel );
406 1 : if ( aPropSet.getProperty( nClassId, PROP_ClassId ) )
407 : {
408 : /* psuedo ripped from legacy msocximex:
409 : "There is a truly horrible thing with EditControls and FormattedField
410 : Controls, they both pretend to have an EDITBOX ClassId for compability
411 : reasons, at some stage in the future hopefully there will be a proper
412 : FormulaField ClassId rather than this piggybacking two controls onto the
413 : same ClassId, cmc." - when fixed the fake FORMULAFIELD id entry
414 : and definition above can be removed/replaced
415 : */
416 1 : if ( nClassId == FormComponentType::TEXTFIELD)
417 : {
418 : Reference< XServiceInfo > xInfo( xCntrlModel,
419 1 : UNO_QUERY);
420 3 : if (xInfo->
421 2 : supportsService( "com.sun.star.form.component.FormattedField" ) )
422 0 : nClassId = FORMULAFIELD;
423 : }
424 0 : else if ( nClassId == FormComponentType::COMMANDBUTTON )
425 : {
426 0 : bool bToggle = false;
427 0 : aPropSet.getProperty( bToggle, PROP_Toggle );
428 0 : if ( bToggle )
429 0 : nClassId = TOGGLEBUTTON;
430 : }
431 0 : else if ( nClassId == FormComponentType::CONTROL )
432 : {
433 : Reference< XServiceInfo > xInfo( xCntrlModel,
434 0 : UNO_QUERY);
435 0 : if (xInfo->supportsService("com.sun.star.form.component.ImageControl" ) )
436 0 : nClassId = FormComponentType::IMAGECONTROL;
437 : }
438 :
439 1 : GUIDCNamePairMap& cntrlMap = classIdToGUIDCNamePairMap::get();
440 1 : GUIDCNamePairMap::iterator it = cntrlMap.find( nClassId );
441 1 : if ( it != cntrlMap.end() )
442 : {
443 1 : aPropSet.getProperty(maName, PROP_Name );
444 1 : maTypeName = OUString::createFromAscii( it->second.sName );
445 1 : maFullName = "Microsoft Forms 2.0 " + maTypeName;
446 1 : maControl = EmbeddedControl( maName );
447 1 : maGUID = OUString::createFromAscii( it->second.sGUID );
448 1 : mpModel = maControl.createModelFromGuid( maGUID );
449 : }
450 1 : }
451 1 : }
452 1 : }
453 :
454 1 : void OleFormCtrlExportHelper::exportName( const Reference< XOutputStream >& rxOut )
455 : {
456 1 : oox::BinaryXOutputStream aOut( rxOut, false );
457 1 : aOut.writeUnicodeArray( maName );
458 1 : aOut << sal_Int32(0);
459 1 : }
460 :
461 1 : void OleFormCtrlExportHelper::exportCompObj( const Reference< XOutputStream >& rxOut )
462 : {
463 1 : oox::BinaryXOutputStream aOut( rxOut, false );
464 1 : if ( mpModel )
465 1 : mpModel->exportCompObj( aOut );
466 1 : }
467 :
468 1 : void OleFormCtrlExportHelper::exportControl( const Reference< XOutputStream >& rxOut, const Size& rSize )
469 : {
470 1 : oox::BinaryXOutputStream aOut( rxOut, false );
471 1 : if ( mpModel )
472 : {
473 1 : ::oox::ole::ControlConverter aConv( mxDocModel, maGrfHelper );
474 1 : maControl.convertFromProperties( mxControlModel, aConv );
475 1 : mpModel->maSize.first = rSize.Width;
476 1 : mpModel->maSize.second = rSize.Height;
477 1 : mpModel->exportBinaryModel( aOut );
478 1 : }
479 1 : }
480 :
481 153 : MSConvertOCXControls::MSConvertOCXControls( const Reference< ::com::sun::star::frame::XModel >& rxModel ) : SvxMSConvertOCXControls( rxModel ), mxCtx( comphelper::getProcessComponentContext() ), maGrfHelper( mxCtx, lcl_getFrame( rxModel ), StorageRef() )
482 : {
483 153 : }
484 :
485 153 : MSConvertOCXControls::~MSConvertOCXControls()
486 : {
487 153 : }
488 :
489 : bool
490 44 : MSConvertOCXControls::importControlFromStream( ::oox::BinaryInputStream& rInStrm, Reference< XFormComponent >& rxFormComp, const OUString& rGuidString )
491 : {
492 44 : ::oox::ole::EmbeddedControl aControl( "Unknown" );
493 44 : if( ::oox::ole::ControlModelBase* pModel = aControl.createModelFromGuid( rGuidString ) )
494 : {
495 30 : pModel->importBinaryModel( rInStrm );
496 30 : rxFormComp.set( mxCtx->getServiceManager()->createInstanceWithContext( pModel->getServiceName(), mxCtx ), UNO_QUERY );
497 30 : Reference< XControlModel > xCtlModel( rxFormComp, UNO_QUERY );
498 60 : ::oox::ole::ControlConverter aConv( mxModel, maGrfHelper );
499 60 : aControl.convertProperties( xCtlModel, aConv );
500 : }
501 44 : return rxFormComp.is();
502 : }
503 :
504 : sal_Bool
505 29 : MSConvertOCXControls::ReadOCXCtlsStream( SotStorageStreamRef& rSrc1, Reference< XFormComponent > & rxFormComp,
506 : sal_Int32 nPos,
507 : sal_Int32 nStreamSize)
508 : {
509 29 : if ( rSrc1.Is() )
510 : {
511 29 : BinaryXInputStream aCtlsStrm( Reference< XInputStream >( new utl::OSeekableInputStreamWrapper( *rSrc1 ) ), true );
512 29 : aCtlsStrm.seek( nPos );
513 58 : OUString aStrmClassId = ::oox::ole::OleHelper::importGuid( aCtlsStrm );
514 58 : return importControlFromStream( aCtlsStrm, rxFormComp, aStrmClassId, nStreamSize );
515 : }
516 0 : return sal_False;
517 : }
518 :
519 44 : bool MSConvertOCXControls::importControlFromStream( ::oox::BinaryInputStream& rInStrm, Reference< XFormComponent >& rxFormComp, const OUString& rStrmClassId,
520 : sal_Int32 nStreamSize)
521 : {
522 44 : if ( !rInStrm.isEof() )
523 : {
524 : // Special processing for those html controls
525 44 : bool bOneOfHtmlControls = false;
526 176 : if ( rStrmClassId.toAsciiUpperCase().equalsAscii( HTML_GUID_SELECT )
527 176 : || rStrmClassId.toAsciiUpperCase().equalsAscii( HTML_GUID_TEXTBOX ) )
528 0 : bOneOfHtmlControls = false;
529 :
530 44 : if ( bOneOfHtmlControls )
531 : {
532 : // html controls don't seem have a handy record length following the GUID
533 : // in the binary stream.
534 : // Given the control stream length create a stream of nStreamSize bytes starting from
535 : // nPos ( offset by the guid already read in )
536 0 : if ( !nStreamSize )
537 0 : return false;
538 0 : const int nGuidSize = 0x10;
539 0 : StreamDataSequence aDataSeq;
540 0 : sal_Int32 nBytesToRead = nStreamSize - nGuidSize;
541 0 : while ( nBytesToRead )
542 0 : nBytesToRead -= rInStrm.readData( aDataSeq, nBytesToRead );
543 0 : SequenceInputStream aInSeqStream( aDataSeq );
544 0 : importControlFromStream( aInSeqStream, rxFormComp, rStrmClassId );
545 : }
546 : else
547 : {
548 44 : importControlFromStream( rInStrm, rxFormComp, rStrmClassId );
549 : }
550 : }
551 44 : return rxFormComp.is();
552 : }
553 :
554 15 : sal_Bool MSConvertOCXControls::ReadOCXStorage( SotStorageRef& xOleStg,
555 : Reference< XFormComponent > & rxFormComp )
556 : {
557 15 : if ( xOleStg.Is() )
558 : {
559 15 : SvStorageStreamRef pNameStream = xOleStg->OpenSotStream( OUString("\3OCXNAME"));
560 29 : BinaryXInputStream aNameStream( Reference< XInputStream >( new utl::OSeekableInputStreamWrapper( *pNameStream ) ), true );
561 :
562 29 : SvStorageStreamRef pContents = xOleStg->OpenSotStream( OUString("contents"));
563 29 : BinaryXInputStream aInStrm( Reference< XInputStream >( new utl::OSeekableInputStreamWrapper( *pContents ) ), true );
564 :
565 :
566 29 : SvStorageStreamRef pClsStrm = xOleStg->OpenSotStream(OUString("\1CompObj"));
567 29 : BinaryXInputStream aClsStrm( Reference< XInputStream >( new utl::OSeekableInputStreamWrapper(*pClsStrm ) ), true );
568 15 : aClsStrm.skip(12);
569 :
570 29 : OUString aStrmClassId = ::oox::ole::OleHelper::importGuid( aClsStrm );
571 15 : if ( importControlFromStream( aInStrm, rxFormComp, aStrmClassId, aInStrm.size() ) )
572 : {
573 1 : OUString aName = aNameStream.readNulUnicodeArray();
574 2 : Reference< XControlModel > xCtlModel( rxFormComp, UNO_QUERY );
575 1 : if ( !aName.isEmpty() && xCtlModel.is() )
576 : {
577 1 : PropertyMap aPropMap;
578 1 : aPropMap.setProperty( PROP_Name, aName );
579 2 : PropertySet aPropSet( xCtlModel );
580 2 : aPropSet.setProperties( aPropMap );
581 : }
582 2 : return rxFormComp.is();
583 14 : }
584 : }
585 14 : return sal_False;
586 : }
587 :
588 0 : sal_Bool MSConvertOCXControls::WriteOCXExcelKludgeStream( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& rxModel, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >& xOutStrm, const com::sun::star::uno::Reference< com::sun::star::awt::XControlModel > &rxControlModel, const com::sun::star::awt::Size& rSize,OUString &rName )
589 : {
590 0 : OleFormCtrlExportHelper exportHelper( comphelper::getProcessComponentContext(), rxModel, rxControlModel );
591 0 : if ( !exportHelper.isValid() )
592 0 : return sal_False;
593 0 : rName = exportHelper.getTypeName();
594 0 : SvGlobalName aName;
595 0 : OUString sId = exportHelper.getGUID();
596 0 : aName.MakeId(sId);
597 0 : BinaryXOutputStream xOut( xOutStrm, false );
598 0 : OleHelper::exportGuid( xOut, aName );
599 0 : exportHelper.exportControl( xOutStrm, rSize );
600 0 : return sal_True;
601 : }
602 :
603 1 : sal_Bool MSConvertOCXControls::WriteOCXStream( const Reference< XModel >& rxModel, SotStorageRef &xOleStg,
604 : const Reference< XControlModel > &rxControlModel,
605 : const com::sun::star::awt::Size& rSize, OUString &rName)
606 : {
607 1 : SvGlobalName aName;
608 :
609 2 : OleFormCtrlExportHelper exportHelper( comphelper::getProcessComponentContext(), rxModel, rxControlModel );
610 :
611 1 : if ( !exportHelper.isValid() )
612 0 : return sal_False;
613 :
614 2 : OUString sId = exportHelper.getGUID();
615 1 : aName.MakeId(sId);
616 :
617 2 : OUString sFullName = exportHelper.getFullName();
618 1 : rName = exportHelper.getTypeName();
619 1 : xOleStg->SetClass( aName,0x5C,sFullName);
620 : {
621 1 : SvStorageStreamRef pNameStream = xOleStg->OpenSotStream(OUString("\3OCXNAME"));
622 2 : Reference< XOutputStream > xOut = new utl::OSeekableOutputStreamWrapper( *pNameStream );
623 2 : exportHelper.exportName( xOut );
624 : }
625 : {
626 1 : SvStorageStreamRef pObjStream = xOleStg->OpenSotStream(OUString("\1CompObj"));
627 2 : Reference< XOutputStream > xOut = new utl::OSeekableOutputStreamWrapper( *pObjStream );
628 2 : exportHelper.exportCompObj( xOut );
629 : }
630 : {
631 1 : SvStorageStreamRef pContents = xOleStg->OpenSotStream(OUString("contents"));
632 2 : Reference< XOutputStream > xOut = new utl::OSeekableOutputStreamWrapper( *pContents );
633 2 : exportHelper.exportControl( xOut, rSize );
634 : }
635 2 : return sal_True;
636 : }
637 :
638 : #ifdef SvxMSConvertOCXControlsRemoved
639 : const Reference< com::sun::star::lang::XMultiServiceFactory > & MSConvertOCXControls::GetServiceFactory()
640 : {
641 : if ( !mxServiceFactory.is() && mxModel.is() )
642 : mxServiceFactory.set( mxModel, UNO_QUERY );
643 : return mxServiceFactory;
644 : }
645 :
646 : const Reference< XIndexContainer >&
647 : MSConvertOCXControls::GetFormComps()
648 : {
649 : if( !mxFormComps.is() )
650 : {
651 : GetDrawPage();
652 : if( mxDrawPage.is() )
653 : {
654 : Reference< XFormsSupplier > xFormsSupplier( mxDrawPage,
655 : UNO_QUERY );
656 : OSL_ENSURE( xFormsSupplier.is(),
657 : "not able to get XFormsSupplier from XDrawPage" );
658 :
659 : Reference< XNameContainer > xNameCont =
660 : xFormsSupplier->getForms();
661 :
662 : OUString sStdName = "WW-Standard";
663 : OUString sName( sStdName );
664 : sal_uInt16 n = 0;
665 :
666 : while( xNameCont->hasByName( sName ) )
667 : {
668 : sName = sStdName;
669 : sName += OUString::number(++n);
670 : }
671 :
672 : const Reference< XMultiServiceFactory > &rServiceFactory
673 : = GetServiceFactory();
674 : if( !rServiceFactory.is() )
675 : return mxFormComps;
676 :
677 : Reference< XInterface > xCreate =
678 : rServiceFactory->createInstance("com.sun.star.form.component.Form");
679 : if( xCreate.is() )
680 : {
681 : Reference< XPropertySet > xFormPropSet( xCreate,
682 : UNO_QUERY );
683 :
684 : Any aTmp(&sName,getCppuType((OUString *)0));
685 : xFormPropSet->setPropertyValue( "Name", aTmp );
686 :
687 : Reference< XForm > xForm( xCreate, UNO_QUERY );
688 : OSL_ENSURE(xForm.is(), "No Form?");
689 :
690 : Reference< XIndexContainer > xForms( xNameCont,
691 : UNO_QUERY );
692 : OSL_ENSURE( xForms.is(), "XForms not available" );
693 :
694 : aTmp.setValue( &xForm,
695 : ::getCppuType((Reference < XForm >*)0));
696 : xForms->insertByIndex( xForms->getCount(), aTmp );
697 :
698 : mxFormComps = Reference< XIndexContainer >
699 : (xCreate, UNO_QUERY);
700 : }
701 : }
702 : }
703 :
704 : return mxFormComps;
705 : }
706 : const Reference< XDrawPage >& MSConvertOCXControls::GetDrawPage()
707 : {
708 : if( !mxDrawPage.is() && mxModel.is() )
709 : {
710 : Reference< XDrawPageSupplier > xTxtDoc(mxModel, UNO_QUERY);
711 : OSL_ENSURE( xTxtDoc.is(),"no XDrawPageSupplier from XModel");
712 : mxDrawPage = xTxtDoc->getDrawPage();
713 : OSL_ENSURE( mxDrawPage.is(), "no XDrawPage" );
714 : }
715 : return mxDrawPage;
716 : }
717 :
718 : const Reference< XShapes >& MSConvertOCXControls::GetShapes()
719 : {
720 : if( !mxShapes.is() )
721 : {
722 : GetDrawPage();
723 : if( mxDrawPage.is() )
724 : {
725 :
726 : mxShapes = Reference< XShapes >(mxDrawPage,
727 : UNO_QUERY);
728 : OSL_ENSURE( mxShapes.is(), "no XShapes from XDrawPage" );
729 : }
730 : }
731 : return mxShapes;
732 : }
733 : #endif
734 : // ============================================================================
735 :
736 : } // namespace ole
737 141 : } // namespace oox
738 :
739 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|