/src/libreoffice/oox/source/ole/olehelper.cxx
Line | Count | Source |
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 <sot/formats.hxx> |
24 | | #include <sot/storage.hxx> |
25 | | #include <osl/diagnose.h> |
26 | | #include <oox/helper/binaryinputstream.hxx> |
27 | | #include <oox/helper/binaryoutputstream.hxx> |
28 | | #include <oox/helper/graphichelper.hxx> |
29 | | #include <oox/token/properties.hxx> |
30 | | #include <oox/token/tokens.hxx> |
31 | | #include <oox/ole/axcontrol.hxx> |
32 | | #include <oox/helper/propertymap.hxx> |
33 | | #include <oox/helper/propertyset.hxx> |
34 | | |
35 | | #include <com/sun/star/awt/XControlModel.hpp> |
36 | | #include <com/sun/star/beans/XPropertySet.hpp> |
37 | | #include <com/sun/star/form/FormComponentType.hpp> |
38 | | #include <com/sun/star/form/XFormComponent.hpp> |
39 | | #include <com/sun/star/frame/XFrame.hpp> |
40 | | #include <com/sun/star/frame/XModel.hpp> |
41 | | #include <com/sun/star/lang/XServiceInfo.hpp> |
42 | | #include <com/sun/star/awt/Size.hpp> |
43 | | #include <com/sun/star/uno/XComponentContext.hpp> |
44 | | |
45 | | #include <tools/globname.hxx> |
46 | | #include <unotools/streamwrap.hxx> |
47 | | #include <comphelper/processfactory.hxx> |
48 | | #include <utility> |
49 | | |
50 | | namespace oox::ole { |
51 | | |
52 | | using ::com::sun::star::form::XFormComponent; |
53 | | using ::com::sun::star::awt::XControlModel; |
54 | | using ::com::sun::star::awt::Size; |
55 | | using ::com::sun::star::frame::XModel; |
56 | | using ::com::sun::star::io::XOutputStream; |
57 | | using ::com::sun::star::io::XInputStream; |
58 | | using ::com::sun::star::beans::XPropertySet; |
59 | | using ::com::sun::star::uno::Reference; |
60 | | using ::com::sun::star::uno::UNO_QUERY; |
61 | | using ::com::sun::star::uno::XComponentContext; |
62 | | using ::com::sun::star::lang::XServiceInfo; |
63 | | |
64 | | using namespace ::com::sun::star::form; |
65 | | |
66 | | namespace { |
67 | | |
68 | | const sal_uInt32 OLE_COLORTYPE_MASK = 0xFF000000; |
69 | | const sal_uInt32 OLE_COLORTYPE_CLIENT = 0x00000000; |
70 | | const sal_uInt32 OLE_COLORTYPE_PALETTE = 0x01000000; |
71 | | const sal_uInt32 OLE_COLORTYPE_BGR = 0x02000000; |
72 | | const sal_uInt32 OLE_COLORTYPE_SYSCOLOR = 0x80000000; |
73 | | |
74 | | const sal_uInt32 OLE_PALETTECOLOR_MASK = 0x0000FFFF; |
75 | | const sal_uInt32 OLE_SYSTEMCOLOR_MASK = 0x0000FFFF; |
76 | | |
77 | | /** Swaps the red and blue component of the passed color. */ |
78 | | sal_uInt32 lclSwapRedBlue( sal_uInt32 nColor ) |
79 | 2 | { |
80 | 2 | return static_cast< sal_uInt32 >( (nColor & 0xFF00FF00) | ((nColor & 0x0000FF) << 16) | ((nColor & 0xFF0000) >> 16) ); |
81 | 2 | } |
82 | | |
83 | | /** Returns the UNO RGB color from the passed encoded OLE BGR color. */ |
84 | | ::Color lclDecodeBgrColor( sal_uInt32 nOleColor ) |
85 | 0 | { |
86 | 0 | return ::Color( ColorTransparency, lclSwapRedBlue( nOleColor ) & 0xFFFFFF ); |
87 | 0 | } |
88 | | |
89 | | const sal_uInt32 OLE_STDPIC_ID = 0x0000746C; |
90 | | |
91 | | struct GUIDCNamePair |
92 | | { |
93 | | const char* sGUID; |
94 | | const char* sName; |
95 | | }; |
96 | | |
97 | | struct IdCntrlData |
98 | | { |
99 | | sal_Int16 nId; |
100 | | GUIDCNamePair aData; |
101 | | }; |
102 | | |
103 | | const sal_Int16 TOGGLEBUTTON = -1; |
104 | | const sal_Int16 FORMULAFIELD = -2; |
105 | | |
106 | | typedef std::map< sal_Int16, GUIDCNamePair > GUIDCNamePairMap; |
107 | | class classIdToGUIDCNamePairMap |
108 | | { |
109 | | GUIDCNamePairMap mnIdToGUIDCNamePairMap; |
110 | | classIdToGUIDCNamePairMap(); |
111 | | public: |
112 | | static GUIDCNamePairMap& get(); |
113 | | }; |
114 | | |
115 | | classIdToGUIDCNamePairMap::classIdToGUIDCNamePairMap() |
116 | 0 | { |
117 | 0 | static IdCntrlData const initialCntrlData[] = |
118 | 0 | { |
119 | | // Command button MUST be at index 0 |
120 | 0 | { FormComponentType::COMMANDBUTTON, |
121 | 0 | { AX_GUID_COMMANDBUTTON, "CommandButton"} , |
122 | 0 | }, |
123 | | // Toggle button MUST be at index 1 |
124 | 0 | { TOGGLEBUTTON, |
125 | 0 | { AX_GUID_TOGGLEBUTTON, "ToggleButton"}, |
126 | 0 | }, |
127 | 0 | { FormComponentType::FIXEDTEXT, |
128 | 0 | { AX_GUID_LABEL, "Label"}, |
129 | 0 | }, |
130 | 0 | { FormComponentType::TEXTFIELD, |
131 | 0 | { AX_GUID_TEXTBOX, "TextBox"}, |
132 | 0 | }, |
133 | 0 | { FormComponentType::LISTBOX, |
134 | 0 | { AX_GUID_LISTBOX, "ListBox"}, |
135 | 0 | }, |
136 | 0 | { FormComponentType::COMBOBOX, |
137 | 0 | { AX_GUID_COMBOBOX, "ComboBox"}, |
138 | 0 | }, |
139 | 0 | { FormComponentType::CHECKBOX, |
140 | 0 | { AX_GUID_CHECKBOX, "CheckBox"}, |
141 | 0 | }, |
142 | 0 | { FormComponentType::RADIOBUTTON, |
143 | 0 | { AX_GUID_OPTIONBUTTON, "OptionButton"}, |
144 | 0 | }, |
145 | 0 | { FormComponentType::IMAGECONTROL, |
146 | 0 | { AX_GUID_IMAGE, "Image"}, |
147 | 0 | }, |
148 | 0 | { FormComponentType::DATEFIELD, |
149 | 0 | { AX_GUID_TEXTBOX, "TextBox"}, |
150 | 0 | }, |
151 | 0 | { FormComponentType::TIMEFIELD, |
152 | 0 | { AX_GUID_TEXTBOX, "TextBox"}, |
153 | 0 | }, |
154 | 0 | { FormComponentType::NUMERICFIELD, |
155 | 0 | { AX_GUID_TEXTBOX, "TextBox"}, |
156 | 0 | }, |
157 | 0 | { FormComponentType::CURRENCYFIELD, |
158 | 0 | { AX_GUID_TEXTBOX, "TextBox"}, |
159 | 0 | }, |
160 | 0 | { FormComponentType::PATTERNFIELD, |
161 | 0 | { AX_GUID_TEXTBOX, "TextBox"}, |
162 | 0 | }, |
163 | 0 | { FORMULAFIELD, |
164 | 0 | { AX_GUID_TEXTBOX, "TextBox"}, |
165 | 0 | }, |
166 | 0 | { FormComponentType::IMAGEBUTTON, |
167 | 0 | { AX_GUID_COMMANDBUTTON, "CommandButton"}, |
168 | 0 | }, |
169 | 0 | { FormComponentType::SPINBUTTON, |
170 | 0 | { AX_GUID_SPINBUTTON, "SpinButton"}, |
171 | 0 | }, |
172 | 0 | { FormComponentType::SCROLLBAR, |
173 | 0 | { AX_GUID_SCROLLBAR, "ScrollBar"}, |
174 | 0 | } |
175 | 0 | }; |
176 | 0 | int const length = std::size( initialCntrlData ); |
177 | 0 | IdCntrlData const * pData = initialCntrlData; |
178 | 0 | for ( int index = 0; index < length; ++index, ++pData ) |
179 | 0 | mnIdToGUIDCNamePairMap[ pData->nId ] = pData->aData; |
180 | 0 | }; |
181 | | |
182 | | GUIDCNamePairMap& classIdToGUIDCNamePairMap::get() |
183 | 0 | { |
184 | 0 | static classIdToGUIDCNamePairMap theInst; |
185 | 0 | return theInst.mnIdToGUIDCNamePairMap; |
186 | 0 | } |
187 | | |
188 | | template< typename Type > |
189 | | void lclAppendHex( OUStringBuffer& orBuffer, Type nValue ) |
190 | 201k | { |
191 | 201k | const sal_Int32 nWidth = 2 * sizeof( Type ); |
192 | 201k | static const sal_Unicode spcHexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; |
193 | 201k | orBuffer.setLength( orBuffer.getLength() + nWidth ); |
194 | 786k | for( sal_Int32 nCharIdx = orBuffer.getLength() - 1, nCharEnd = nCharIdx - nWidth; nCharIdx > nCharEnd; --nCharIdx, nValue >>= 4 ) |
195 | 585k | orBuffer[nCharIdx] = spcHexChars[ nValue & 0xF ]; |
196 | 201k | } olehelper.cxx:void oox::ole::(anonymous namespace)::lclAppendHex<unsigned int>(rtl::OUStringBuffer&, unsigned int) Line | Count | Source | 190 | 18.2k | { | 191 | 18.2k | const sal_Int32 nWidth = 2 * sizeof( Type ); | 192 | 18.2k | static const sal_Unicode spcHexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; | 193 | 18.2k | orBuffer.setLength( orBuffer.getLength() + nWidth ); | 194 | 164k | for( sal_Int32 nCharIdx = orBuffer.getLength() - 1, nCharEnd = nCharIdx - nWidth; nCharIdx > nCharEnd; --nCharIdx, nValue >>= 4 ) | 195 | 146k | orBuffer[nCharIdx] = spcHexChars[ nValue & 0xF ]; | 196 | 18.2k | } |
olehelper.cxx:void oox::ole::(anonymous namespace)::lclAppendHex<unsigned short>(rtl::OUStringBuffer&, unsigned short) Line | Count | Source | 190 | 36.5k | { | 191 | 36.5k | const sal_Int32 nWidth = 2 * sizeof( Type ); | 192 | 36.5k | static const sal_Unicode spcHexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; | 193 | 36.5k | orBuffer.setLength( orBuffer.getLength() + nWidth ); | 194 | 182k | for( sal_Int32 nCharIdx = orBuffer.getLength() - 1, nCharEnd = nCharIdx - nWidth; nCharIdx > nCharEnd; --nCharIdx, nValue >>= 4 ) | 195 | 146k | orBuffer[nCharIdx] = spcHexChars[ nValue & 0xF ]; | 196 | 36.5k | } |
olehelper.cxx:void oox::ole::(anonymous namespace)::lclAppendHex<unsigned char>(rtl::OUStringBuffer&, unsigned char) Line | Count | Source | 190 | 146k | { | 191 | 146k | const sal_Int32 nWidth = 2 * sizeof( Type ); | 192 | 146k | static const sal_Unicode spcHexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; | 193 | 146k | orBuffer.setLength( orBuffer.getLength() + nWidth ); | 194 | 439k | for( sal_Int32 nCharIdx = orBuffer.getLength() - 1, nCharEnd = nCharIdx - nWidth; nCharIdx > nCharEnd; --nCharIdx, nValue >>= 4 ) | 195 | 292k | orBuffer[nCharIdx] = spcHexChars[ nValue & 0xF ]; | 196 | 146k | } |
|
197 | | |
198 | | } // namespace |
199 | | |
200 | | StdFontInfo::StdFontInfo() : |
201 | 0 | mnHeight( 0 ), |
202 | 0 | mnWeight( OLE_STDFONT_NORMAL ), |
203 | 0 | mnCharSet( WINDOWS_CHARSET_ANSI ), |
204 | 0 | mnFlags( 0 ) |
205 | 0 | { |
206 | 0 | } |
207 | | |
208 | | StdFontInfo::StdFontInfo( OUString aName, sal_uInt32 nHeight ) : |
209 | 0 | maName(std::move( aName )), |
210 | 0 | mnHeight( nHeight ), |
211 | 0 | mnWeight( OLE_STDFONT_NORMAL ), |
212 | 0 | mnCharSet( WINDOWS_CHARSET_ANSI ), |
213 | 0 | mnFlags( 0 ) |
214 | 0 | { |
215 | 0 | } |
216 | | |
217 | | ::Color OleHelper::decodeOleColor( |
218 | | const GraphicHelper& rGraphicHelper, sal_uInt32 nOleColor, bool bDefaultColorBgr ) |
219 | 0 | { |
220 | 0 | static const sal_Int32 spnSystemColors[] = |
221 | 0 | { |
222 | 0 | XML_scrollBar, XML_background, XML_activeCaption, XML_inactiveCaption, |
223 | 0 | XML_menu, XML_window, XML_windowFrame, XML_menuText, |
224 | 0 | XML_windowText, XML_captionText, XML_activeBorder, XML_inactiveBorder, |
225 | 0 | XML_appWorkspace, XML_highlight, XML_highlightText, XML_btnFace, |
226 | 0 | XML_btnShadow, XML_grayText, XML_btnText, XML_inactiveCaptionText, |
227 | 0 | XML_btnHighlight, XML_3dDkShadow, XML_3dLight, XML_infoText, |
228 | 0 | XML_infoBk |
229 | 0 | }; |
230 | |
|
231 | 0 | switch( nOleColor & OLE_COLORTYPE_MASK ) |
232 | 0 | { |
233 | 0 | case OLE_COLORTYPE_CLIENT: |
234 | 0 | return bDefaultColorBgr ? lclDecodeBgrColor( nOleColor ) : rGraphicHelper.getPaletteColor( nOleColor & OLE_PALETTECOLOR_MASK ); |
235 | | |
236 | 0 | case OLE_COLORTYPE_PALETTE: |
237 | 0 | return rGraphicHelper.getPaletteColor( nOleColor & OLE_PALETTECOLOR_MASK ); |
238 | | |
239 | 0 | case OLE_COLORTYPE_BGR: |
240 | 0 | return lclDecodeBgrColor( nOleColor ); |
241 | | |
242 | 0 | case OLE_COLORTYPE_SYSCOLOR: |
243 | 0 | return rGraphicHelper.getSystemColor( STATIC_ARRAY_SELECT( spnSystemColors, nOleColor & OLE_SYSTEMCOLOR_MASK, XML_TOKEN_INVALID ), API_RGB_WHITE ); |
244 | 0 | } |
245 | 0 | OSL_FAIL( "OleHelper::decodeOleColor - unknown color type" ); |
246 | 0 | return API_RGB_BLACK; |
247 | 0 | } |
248 | | |
249 | | sal_uInt32 OleHelper::encodeOleColor( sal_Int32 nRgbColor ) |
250 | 2 | { |
251 | 2 | return OLE_COLORTYPE_BGR | lclSwapRedBlue( static_cast< sal_uInt32 >( nRgbColor & 0xFFFFFF ) ); |
252 | 2 | } |
253 | | |
254 | | void OleHelper::exportGuid( BinaryOutputStream& rOStr, const SvGlobalName& rId ) |
255 | 0 | { |
256 | 0 | rOStr.WriteUInt32( rId.GetCLSID().Data1 ); |
257 | 0 | rOStr.WriteUInt16( rId.GetCLSID().Data2 ); |
258 | 0 | rOStr.WriteUInt16( rId.GetCLSID().Data3 ); |
259 | 0 | rOStr.writeArray( rId.GetCLSID().Data4, 8 ); |
260 | 0 | } |
261 | | |
262 | | OUString OleHelper::importGuid( BinaryInputStream& rInStrm ) |
263 | 18.2k | { |
264 | 18.2k | OUStringBuffer aBuffer(40); |
265 | 18.2k | aBuffer.append( '{' ); |
266 | 18.2k | lclAppendHex( aBuffer, rInStrm.readuInt32() ); |
267 | 18.2k | aBuffer.append( '-' ); |
268 | 18.2k | lclAppendHex( aBuffer, rInStrm.readuInt16() ); |
269 | 18.2k | aBuffer.append( '-' ); |
270 | 18.2k | lclAppendHex( aBuffer, rInStrm.readuInt16() ); |
271 | 18.2k | aBuffer.append( '-' ); |
272 | 18.2k | lclAppendHex( aBuffer, rInStrm.readuInt8() ); |
273 | 18.2k | lclAppendHex( aBuffer, rInStrm.readuInt8() ); |
274 | 18.2k | aBuffer.append( '-' ); |
275 | 128k | for( int nIndex = 0; nIndex < 6; ++nIndex ) |
276 | 109k | lclAppendHex( aBuffer, rInStrm.readuInt8() ); |
277 | 18.2k | aBuffer.append( '}' ); |
278 | 18.2k | return aBuffer.makeStringAndClear(); |
279 | 18.2k | } |
280 | | |
281 | | bool OleHelper::importStdFont( StdFontInfo& orFontInfo, BinaryInputStream& rInStrm, bool bWithGuid ) |
282 | 0 | { |
283 | 0 | if( bWithGuid ) |
284 | 0 | { |
285 | 0 | bool bIsStdFont = importGuid( rInStrm ) == OLE_GUID_STDFONT; |
286 | 0 | OSL_ENSURE( bIsStdFont, "OleHelper::importStdFont - unexpected header GUID, expected StdFont" ); |
287 | 0 | if( !bIsStdFont ) |
288 | 0 | return false; |
289 | 0 | } |
290 | | |
291 | 0 | sal_uInt8 nVersion, nNameLen; |
292 | 0 | nVersion = rInStrm.readuChar(); |
293 | 0 | orFontInfo.mnCharSet = rInStrm.readuInt16(); |
294 | 0 | orFontInfo.mnFlags = rInStrm.readuChar(); |
295 | 0 | orFontInfo.mnWeight = rInStrm.readuInt16(); |
296 | 0 | orFontInfo.mnHeight = rInStrm.readuInt32(); |
297 | 0 | nNameLen = rInStrm.readuChar(); |
298 | | // according to spec the name is ASCII |
299 | 0 | orFontInfo.maName = rInStrm.readCharArrayUC( nNameLen, RTL_TEXTENCODING_ASCII_US ); |
300 | 0 | OSL_ENSURE( nVersion <= 1, "OleHelper::importStdFont - wrong version" ); |
301 | 0 | return !rInStrm.isEof() && (nVersion <= 1); |
302 | 0 | } |
303 | | |
304 | | bool OleHelper::importStdPic( StreamDataSequence& orGraphicData, BinaryInputStream& rInStrm ) |
305 | 0 | { |
306 | 0 | bool bIsStdPic = importGuid( rInStrm ) == OLE_GUID_STDPIC; |
307 | 0 | OSL_ENSURE( bIsStdPic, "OleHelper::importStdPic - unexpected header GUID, expected StdPic" ); |
308 | 0 | if( !bIsStdPic ) |
309 | 0 | return false; |
310 | | |
311 | 0 | sal_uInt32 nStdPicId; |
312 | 0 | sal_Int32 nBytes; |
313 | 0 | nStdPicId = rInStrm.readuInt32(); |
314 | 0 | nBytes = rInStrm.readInt32(); |
315 | 0 | OSL_ENSURE( nStdPicId == OLE_STDPIC_ID, "OleHelper::importStdPic - unexpected header version" ); |
316 | 0 | return !rInStrm.isEof() && (nStdPicId == OLE_STDPIC_ID) && (nBytes > 0) && (rInStrm.readData( orGraphicData, nBytes ) == nBytes); |
317 | 0 | } |
318 | | |
319 | | static Reference< css::frame::XFrame > lcl_getFrame( const Reference< css::frame::XModel >& rxModel ) |
320 | 16.6k | { |
321 | 16.6k | Reference< css::frame::XFrame > xFrame; |
322 | 16.6k | if ( rxModel.is() ) |
323 | 16.6k | { |
324 | 16.6k | Reference< css::frame::XController > xController = rxModel->getCurrentController(); |
325 | 16.6k | xFrame = xController.is() ? xController->getFrame() : nullptr; |
326 | 16.6k | } |
327 | 16.6k | return xFrame; |
328 | 16.6k | } |
329 | | |
330 | 0 | OleFormCtrlExportHelper::OleFormCtrlExportHelper( const Reference< XComponentContext >& rxCtx, const Reference< XModel >& rxDocModel, const Reference< XControlModel >& xCntrlModel ) : mpModel( nullptr ), maGrfHelper( rxCtx, lcl_getFrame( rxDocModel ), StorageRef() ), mxDocModel( rxDocModel ), mxControlModel( xCntrlModel ) |
331 | 0 | { |
332 | | // try to get the guid |
333 | 0 | Reference< css::beans::XPropertySet > xProps( xCntrlModel, UNO_QUERY ); |
334 | 0 | if ( !xProps.is() ) |
335 | 0 | return; |
336 | | |
337 | 0 | sal_Int16 nClassId = 0; |
338 | 0 | PropertySet aPropSet( mxControlModel ); |
339 | 0 | if ( !aPropSet.getProperty( nClassId, PROP_ClassId ) ) |
340 | 0 | return; |
341 | | |
342 | | /* pseudo ripped from legacy msocximex: |
343 | | "There is a truly horrible thing with EditControls and FormattedField |
344 | | Controls, they both pretend to have an EDITBOX ClassId for compatibility |
345 | | reasons, at some stage in the future hopefully there will be a proper |
346 | | FormulaField ClassId rather than this piggybacking two controls onto the |
347 | | same ClassId, cmc." - when fixed the fake FORMULAFIELD id entry |
348 | | and definition above can be removed/replaced |
349 | | */ |
350 | 0 | if ( nClassId == FormComponentType::TEXTFIELD) |
351 | 0 | { |
352 | 0 | Reference< XServiceInfo > xInfo( xCntrlModel, |
353 | 0 | UNO_QUERY); |
354 | 0 | if (xInfo-> |
355 | 0 | supportsService( u"com.sun.star.form.component.FormattedField"_ustr ) ) |
356 | 0 | nClassId = FORMULAFIELD; |
357 | 0 | } |
358 | 0 | else if ( nClassId == FormComponentType::COMMANDBUTTON ) |
359 | 0 | { |
360 | 0 | bool bToggle = false; |
361 | 0 | if ( aPropSet.getProperty( bToggle, PROP_Toggle ) && bToggle ) |
362 | 0 | nClassId = TOGGLEBUTTON; |
363 | 0 | } |
364 | 0 | else if ( nClassId == FormComponentType::CONTROL ) |
365 | 0 | { |
366 | 0 | Reference< XServiceInfo > xInfo( xCntrlModel, |
367 | 0 | UNO_QUERY); |
368 | 0 | if (xInfo->supportsService(u"com.sun.star.form.component.ImageControl"_ustr ) ) |
369 | 0 | nClassId = FormComponentType::IMAGECONTROL; |
370 | 0 | } |
371 | |
|
372 | 0 | GUIDCNamePairMap& cntrlMap = classIdToGUIDCNamePairMap::get(); |
373 | 0 | GUIDCNamePairMap::iterator it = cntrlMap.find( nClassId ); |
374 | 0 | if ( it != cntrlMap.end() ) |
375 | 0 | { |
376 | 0 | aPropSet.getProperty(maName, PROP_Name ); |
377 | 0 | maTypeName = OUString::createFromAscii( it->second.sName ); |
378 | 0 | maFullName = "Microsoft Forms 2.0 " + maTypeName; |
379 | 0 | mpControl.reset(new EmbeddedControl( maName )); |
380 | 0 | maGUID = OUString::createFromAscii( it->second.sGUID ); |
381 | 0 | mpModel = mpControl->createModelFromGuid( maGUID ); |
382 | 0 | } |
383 | 0 | } |
384 | | |
385 | | OleFormCtrlExportHelper::~OleFormCtrlExportHelper() |
386 | 0 | { |
387 | 0 | } |
388 | | |
389 | | void OleFormCtrlExportHelper::exportName( const Reference< XOutputStream >& rxOut ) |
390 | 0 | { |
391 | 0 | oox::BinaryXOutputStream aOut( rxOut, false ); |
392 | 0 | aOut.writeUnicodeArray( maName ); |
393 | 0 | aOut.WriteInt32(0); |
394 | 0 | } |
395 | | |
396 | | void OleFormCtrlExportHelper::exportCompObj( const Reference< XOutputStream >& rxOut ) |
397 | 0 | { |
398 | 0 | oox::BinaryXOutputStream aOut( rxOut, false ); |
399 | 0 | if ( mpModel ) |
400 | 0 | mpModel->exportCompObj( aOut ); |
401 | 0 | } |
402 | | |
403 | | void OleFormCtrlExportHelper::exportControl( const Reference< XOutputStream >& rxOut, const Size& rSize, bool bAutoClose ) |
404 | 0 | { |
405 | 0 | oox::BinaryXOutputStream aOut( rxOut, bAutoClose ); |
406 | 0 | if ( mpModel ) |
407 | 0 | { |
408 | 0 | ::oox::ole::ControlConverter aConv( mxDocModel, maGrfHelper ); |
409 | 0 | if(mpControl) |
410 | 0 | mpControl->convertFromProperties( mxControlModel, aConv ); |
411 | 0 | mpModel->maSize.first = rSize.Width; |
412 | 0 | mpModel->maSize.second = rSize.Height; |
413 | 0 | mpModel->exportBinaryModel( aOut ); |
414 | 0 | } |
415 | 0 | } |
416 | | |
417 | 16.6k | MSConvertOCXControls::MSConvertOCXControls( const Reference< css::frame::XModel >& rxModel ) : SvxMSConvertOCXControls( rxModel ), mxCtx( comphelper::getProcessComponentContext() ), maGrfHelper( mxCtx, lcl_getFrame( rxModel ), StorageRef() ) |
418 | 16.6k | { |
419 | 16.6k | } |
420 | | |
421 | | MSConvertOCXControls::~MSConvertOCXControls() |
422 | 16.6k | { |
423 | 16.6k | } |
424 | | |
425 | | bool |
426 | | MSConvertOCXControls::importControlFromStream( ::oox::BinaryInputStream& rInStrm, Reference< XFormComponent >& rxFormComp, std::u16string_view rGuidString ) |
427 | 18.2k | { |
428 | 18.2k | ::oox::ole::EmbeddedControl aControl( u"Unknown"_ustr ); |
429 | 18.2k | if( ::oox::ole::ControlModelBase* pModel = aControl.createModelFromGuid( rGuidString ) ) |
430 | 0 | { |
431 | 0 | pModel->importBinaryModel( rInStrm ); |
432 | 0 | rxFormComp.set( mxCtx->getServiceManager()->createInstanceWithContext( pModel->getServiceName(), mxCtx ), UNO_QUERY ); |
433 | 0 | Reference< XControlModel > xCtlModel( rxFormComp, UNO_QUERY ); |
434 | 0 | ::oox::ole::ControlConverter aConv( mxModel, maGrfHelper ); |
435 | 0 | aControl.convertProperties( xCtlModel, aConv ); |
436 | 0 | } |
437 | 18.2k | return rxFormComp.is(); |
438 | 18.2k | } |
439 | | |
440 | | bool |
441 | | MSConvertOCXControls::ReadOCXCtlsStream( rtl::Reference<SotStorageStream> const & rSrc1, Reference< XFormComponent > & rxFormComp, |
442 | | sal_Int32 nPos, |
443 | | sal_Int32 nStreamSize) |
444 | 0 | { |
445 | 0 | if ( rSrc1.is() ) |
446 | 0 | { |
447 | 0 | BinaryXInputStream aCtlsStrm( Reference< XInputStream >( new utl::OSeekableInputStreamWrapper( *rSrc1 ) ), true ); |
448 | 0 | aCtlsStrm.seek( nPos ); |
449 | 0 | OUString aStrmClassId = ::oox::ole::OleHelper::importGuid( aCtlsStrm ); |
450 | 0 | return importControlFromStream( aCtlsStrm, rxFormComp, aStrmClassId, nStreamSize ); |
451 | 0 | } |
452 | 0 | return false; |
453 | 0 | } |
454 | | |
455 | | bool MSConvertOCXControls::importControlFromStream( ::oox::BinaryInputStream& rInStrm, Reference< XFormComponent >& rxFormComp, const OUString& rStrmClassId, |
456 | | sal_Int32 nStreamSize) |
457 | 18.2k | { |
458 | 18.2k | if ( !rInStrm.isEof() ) |
459 | 18.2k | { |
460 | | // Special processing for those html controls |
461 | 18.2k | bool bOneOfHtmlControls = false; |
462 | 18.2k | if ( rStrmClassId.toAsciiUpperCase() == HTML_GUID_SELECT |
463 | 18.2k | || rStrmClassId.toAsciiUpperCase() == HTML_GUID_TEXTBOX ) |
464 | 0 | bOneOfHtmlControls = true; |
465 | | |
466 | 18.2k | if ( bOneOfHtmlControls ) |
467 | 0 | { |
468 | | // html controls don't seem have a handy record length following the GUID |
469 | | // in the binary stream. |
470 | | // Given the control stream length create a stream of nStreamSize bytes starting from |
471 | | // nPos ( offset by the guid already read in ) |
472 | 0 | if ( !nStreamSize ) |
473 | 0 | return false; |
474 | 0 | const int nGuidSize = 0x10; |
475 | 0 | StreamDataSequence aDataSeq; |
476 | 0 | sal_Int32 nBytesToRead = nStreamSize - nGuidSize; |
477 | 0 | while ( nBytesToRead ) |
478 | 0 | nBytesToRead -= rInStrm.readData( aDataSeq, nBytesToRead ); |
479 | 0 | SequenceInputStream aInSeqStream( aDataSeq ); |
480 | 0 | importControlFromStream( aInSeqStream, rxFormComp, rStrmClassId ); |
481 | 0 | } |
482 | 18.2k | else |
483 | 18.2k | { |
484 | 18.2k | importControlFromStream( rInStrm, rxFormComp, rStrmClassId ); |
485 | 18.2k | } |
486 | 18.2k | } |
487 | 18.2k | return rxFormComp.is(); |
488 | 18.2k | } |
489 | | |
490 | | bool MSConvertOCXControls::ReadOCXStorage( rtl::Reference<SotStorage> const & xOleStg, |
491 | | Reference< XFormComponent > & rxFormComp ) |
492 | 18.2k | { |
493 | 18.2k | if ( xOleStg.is() ) |
494 | 18.2k | { |
495 | 18.2k | rtl::Reference<SotStorageStream> pNameStream = xOleStg->OpenSotStream(u"\3OCXNAME"_ustr, StreamMode::READ); |
496 | 18.2k | BinaryXInputStream aNameStream( Reference< XInputStream >( new utl::OSeekableInputStreamWrapper( *pNameStream ) ), true ); |
497 | | |
498 | 18.2k | rtl::Reference<SotStorageStream> pContents = xOleStg->OpenSotStream(u"contents"_ustr, StreamMode::READ); |
499 | 18.2k | BinaryXInputStream aInStrm( Reference< XInputStream >( new utl::OSeekableInputStreamWrapper( *pContents ) ), true ); |
500 | | |
501 | 18.2k | rtl::Reference<SotStorageStream> pClsStrm = xOleStg->OpenSotStream(u"\1CompObj"_ustr, StreamMode::READ); |
502 | 18.2k | BinaryXInputStream aClsStrm( Reference< XInputStream >( new utl::OSeekableInputStreamWrapper(*pClsStrm ) ), true ); |
503 | 18.2k | aClsStrm.skip(12); |
504 | | |
505 | 18.2k | OUString aStrmClassId = ::oox::ole::OleHelper::importGuid( aClsStrm ); |
506 | 18.2k | if ( importControlFromStream( aInStrm, rxFormComp, aStrmClassId, aInStrm.size() ) ) |
507 | 0 | { |
508 | 0 | OUString aName = aNameStream.readNulUnicodeArray(); |
509 | 0 | Reference< XControlModel > xCtlModel( rxFormComp, UNO_QUERY ); |
510 | 0 | if ( !aName.isEmpty() && xCtlModel.is() ) |
511 | 0 | { |
512 | 0 | PropertyMap aPropMap; |
513 | 0 | aPropMap.setProperty( PROP_Name, aName ); |
514 | 0 | PropertySet aPropSet( xCtlModel ); |
515 | 0 | aPropSet.setProperties( aPropMap ); |
516 | 0 | } |
517 | 0 | return rxFormComp.is(); |
518 | 0 | } |
519 | 18.2k | } |
520 | 18.2k | return false; |
521 | 18.2k | } |
522 | | |
523 | | bool MSConvertOCXControls::WriteOCXExcelKludgeStream( const css::uno::Reference< css::frame::XModel >& rxModel, const css::uno::Reference< css::io::XOutputStream >& xOutStrm, const css::uno::Reference< css::awt::XControlModel > &rxControlModel, const css::awt::Size& rSize,OUString &rName ) |
524 | 0 | { |
525 | 0 | OleFormCtrlExportHelper exportHelper( comphelper::getProcessComponentContext(), rxModel, rxControlModel ); |
526 | 0 | if ( !exportHelper.isValid() ) |
527 | 0 | return false; |
528 | 0 | rName = exportHelper.getTypeName(); |
529 | 0 | SvGlobalName aName; |
530 | 0 | (void)aName.MakeId(exportHelper.getGUID()); |
531 | 0 | BinaryXOutputStream aOut( xOutStrm, false ); |
532 | 0 | OleHelper::exportGuid( aOut, aName ); |
533 | 0 | exportHelper.exportControl( xOutStrm, rSize ); |
534 | 0 | return true; |
535 | 0 | } |
536 | | |
537 | | bool MSConvertOCXControls::WriteOCXStream( const Reference< XModel >& rxModel, rtl::Reference<SotStorage> const &xOleStg, |
538 | | const Reference< XControlModel > &rxControlModel, |
539 | | const css::awt::Size& rSize, OUString &rName) |
540 | 0 | { |
541 | 0 | SvGlobalName aName; |
542 | |
|
543 | 0 | OleFormCtrlExportHelper exportHelper( comphelper::getProcessComponentContext(), rxModel, rxControlModel ); |
544 | |
|
545 | 0 | if ( !exportHelper.isValid() ) |
546 | 0 | return false; |
547 | | |
548 | 0 | aName.MakeId(exportHelper.getGUID()); |
549 | |
|
550 | 0 | OUString sFullName = exportHelper.getFullName(); |
551 | 0 | rName = exportHelper.getTypeName(); |
552 | 0 | xOleStg->SetClass( aName, SotClipboardFormatId::EMBEDDED_OBJ_OLE, sFullName); |
553 | 0 | { |
554 | 0 | rtl::Reference<SotStorageStream> pNameStream = xOleStg->OpenSotStream(u"\3OCXNAME"_ustr); |
555 | 0 | Reference< XOutputStream > xOut = new utl::OSeekableOutputStreamWrapper( *pNameStream ); |
556 | 0 | exportHelper.exportName( xOut ); |
557 | 0 | } |
558 | 0 | { |
559 | 0 | rtl::Reference<SotStorageStream> pObjStream = xOleStg->OpenSotStream(u"\1CompObj"_ustr); |
560 | 0 | Reference< XOutputStream > xOut = new utl::OSeekableOutputStreamWrapper( *pObjStream ); |
561 | 0 | exportHelper.exportCompObj( xOut ); |
562 | 0 | } |
563 | 0 | { |
564 | 0 | rtl::Reference<SotStorageStream> pContents = xOleStg->OpenSotStream(u"contents"_ustr); |
565 | 0 | Reference< XOutputStream > xOut = new utl::OSeekableOutputStreamWrapper( *pContents ); |
566 | 0 | exportHelper.exportControl( xOut, rSize ); |
567 | 0 | } |
568 | 0 | return true; |
569 | 0 | } |
570 | | |
571 | | } // namespace oox |
572 | | |
573 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |