Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sc / source / filter / excel / xiescher.cxx
blobfe59a3495ba4fae2604cff714ddeae7d681a5b9a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <xiescher.hxx>
22 #include <com/sun/star/beans/NamedValue.hpp>
23 #include <com/sun/star/container/XIndexContainer.hpp>
24 #include <com/sun/star/container/XNameContainer.hpp>
25 #include <com/sun/star/embed/Aspects.hpp>
26 #include <com/sun/star/embed/XEmbeddedObject.hpp>
27 #include <com/sun/star/embed/XEmbedPersist.hpp>
28 #include <com/sun/star/awt/PushButtonType.hpp>
29 #include <com/sun/star/awt/ScrollBarOrientation.hpp>
30 #include <com/sun/star/awt/VisualEffect.hpp>
31 #include <com/sun/star/style/VerticalAlignment.hpp>
32 #include <com/sun/star/drawing/XControlShape.hpp>
33 #include <com/sun/star/form/XForm.hpp>
34 #include <com/sun/star/form/XFormsSupplier.hpp>
35 #include <com/sun/star/form/binding/XBindableValue.hpp>
36 #include <com/sun/star/form/binding/XValueBinding.hpp>
37 #include <com/sun/star/form/binding/XListEntrySink.hpp>
38 #include <com/sun/star/form/binding/XListEntrySource.hpp>
39 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
40 #include <com/sun/star/script/XEventAttacherManager.hpp>
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include <com/sun/star/frame/XModel.hpp>
44 #include <sfx2/objsh.hxx>
45 #include <unotools/moduleoptions.hxx>
46 #include <unotools/fltrcfg.hxx>
47 #include <vcl/dibtools.hxx>
48 #include <vcl/gdimtf.hxx>
49 #include <vcl/window.hxx>
50 #include <vcl/wmf.hxx>
51 #include <comphelper/classids.hxx>
52 #include <comphelper/documentinfo.hxx>
53 #include <toolkit/helper/vclunohelper.hxx>
54 #include <basegfx/point/b2dpoint.hxx>
55 #include <basegfx/polygon/b2dpolygon.hxx>
56 #include <sal/log.hxx>
58 #include <svx/svdopath.hxx>
59 #include <svx/svdocirc.hxx>
60 #include <svx/svdoedge.hxx>
61 #include <svx/svdogrp.hxx>
62 #include <svx/svdoashp.hxx>
63 #include <svx/svdograf.hxx>
64 #include <svx/svdoole2.hxx>
65 #include <svx/svdouno.hxx>
66 #include <svx/svdpage.hxx>
67 #include <editeng/editobj.hxx>
68 #include <editeng/outliner.hxx>
69 #include <editeng/outlobj.hxx>
70 #include <svx/svditer.hxx>
71 #include <editeng/writingmodeitem.hxx>
72 #include <svx/xlnclit.hxx>
73 #include <svx/xlndsit.hxx>
74 #include <svx/xlnedcit.hxx>
75 #include <svx/xlnedit.hxx>
76 #include <svx/xlnedwit.hxx>
77 #include <svx/xlnstcit.hxx>
78 #include <svx/xlnstit.hxx>
79 #include <svx/xlnstwit.hxx>
80 #include <svx/xlnwtit.hxx>
81 #include <svx/sdasitm.hxx>
82 #include <svx/sdshcitm.hxx>
83 #include <svx/sdshitm.hxx>
84 #include <svx/sdsxyitm.hxx>
85 #include <svx/sdtagitm.hxx>
86 #include <svx/sdtditm.hxx>
88 #include <editeng/eeitem.hxx>
89 #include <svx/xflclit.hxx>
90 #include <sal/macros.h>
91 #include <editeng/adjustitem.hxx>
92 #include <svx/xfillit0.hxx>
93 #include <svx/xlineit0.hxx>
94 #include <svx/xlinjoit.hxx>
95 #include <svx/xlntrit.hxx>
96 #include <svx/xbtmpit.hxx>
97 #include <svx/xbitmap.hxx>
98 #include <svtools/embedhlp.hxx>
99 #include <sot/storage.hxx>
101 #include <document.hxx>
102 #include <drwlayer.hxx>
103 #include <userdat.hxx>
104 #include <unonames.hxx>
105 #include <convuno.hxx>
106 #include <postit.hxx>
107 #include <globstr.hrc>
108 #include <scresid.hxx>
110 #include <fprogressbar.hxx>
111 #include <xltracer.hxx>
112 #include <xistream.hxx>
113 #include <xihelper.hxx>
114 #include <xiformula.hxx>
115 #include <xilink.hxx>
116 #include <xistyle.hxx>
117 #include <xipage.hxx>
118 #include <xichart.hxx>
119 #include <xicontent.hxx>
120 #include <scextopt.hxx>
122 #include <namebuff.hxx>
123 #include <sfx2/docfile.hxx>
124 #include <memory>
125 #include <numeric>
126 #include <utility>
128 using namespace com::sun::star;
129 using ::com::sun::star::uno::makeAny;
130 using ::com::sun::star::uno::Any;
131 using ::com::sun::star::beans::XPropertySet;
132 using ::com::sun::star::uno::makeAny;
133 using ::com::sun::star::uno::Exception;
134 using ::com::sun::star::uno::Reference;
135 using ::com::sun::star::uno::Sequence;
136 using ::com::sun::star::uno::UNO_QUERY;
137 using ::com::sun::star::uno::UNO_QUERY_THROW;
138 using ::com::sun::star::uno::UNO_SET_THROW;
139 using ::com::sun::star::beans::NamedValue;
140 using ::com::sun::star::lang::XMultiServiceFactory;
141 using ::com::sun::star::container::XIndexContainer;
142 using ::com::sun::star::container::XNameContainer;
143 using ::com::sun::star::frame::XModel;
144 using ::com::sun::star::awt::XControlModel;
145 using ::com::sun::star::embed::XEmbeddedObject;
146 using ::com::sun::star::embed::XEmbedPersist;
147 using ::com::sun::star::drawing::XControlShape;
148 using ::com::sun::star::drawing::XShape;
149 using ::com::sun::star::form::XFormComponent;
150 using ::com::sun::star::form::XFormsSupplier;
151 using ::com::sun::star::form::binding::XBindableValue;
152 using ::com::sun::star::form::binding::XValueBinding;
153 using ::com::sun::star::form::binding::XListEntrySink;
154 using ::com::sun::star::form::binding::XListEntrySource;
155 using ::com::sun::star::script::ScriptEventDescriptor;
156 using ::com::sun::star::script::XEventAttacherManager;
157 using ::com::sun::star::table::CellAddress;
158 using ::com::sun::star::table::CellRangeAddress;
160 // Drawing objects ============================================================
162 XclImpDrawObjBase::XclImpDrawObjBase( const XclImpRoot& rRoot ) :
163 XclImpRoot( rRoot ),
164 mnObjId( EXC_OBJ_INVALID_ID ),
165 mnTab( 0 ),
166 mnObjType( EXC_OBJTYPE_UNKNOWN ),
167 mnDffShapeId( 0 ),
168 mnDffFlags( ShapeFlag::NONE ),
169 mbHasAnchor( false ),
170 mbHidden( false ),
171 mbVisible( true ),
172 mbPrintable( true ),
173 mbAreaObj( false ),
174 mbAutoMargin( true ),
175 mbSimpleMacro( true ),
176 mbProcessSdr( true ),
177 mbInsertSdr( true ),
178 mbCustomDff( false ),
179 mbNotifyMacroEventRead( false )
183 XclImpDrawObjBase::~XclImpDrawObjBase()
187 XclImpDrawObjRef XclImpDrawObjBase::ReadObj3( const XclImpRoot& rRoot, XclImpStream& rStrm )
189 XclImpDrawObjRef xDrawObj;
191 if( rStrm.GetRecLeft() >= 30 )
193 sal_uInt16 nObjType;
194 rStrm.Ignore( 4 );
195 nObjType = rStrm.ReaduInt16();
196 switch( nObjType )
198 case EXC_OBJTYPE_GROUP: xDrawObj.reset( new XclImpGroupObj( rRoot ) ); break;
199 case EXC_OBJTYPE_LINE: xDrawObj.reset( new XclImpLineObj( rRoot ) ); break;
200 case EXC_OBJTYPE_RECTANGLE: xDrawObj.reset( new XclImpRectObj( rRoot ) ); break;
201 case EXC_OBJTYPE_OVAL: xDrawObj.reset( new XclImpOvalObj( rRoot ) ); break;
202 case EXC_OBJTYPE_ARC: xDrawObj.reset( new XclImpArcObj( rRoot ) ); break;
203 case EXC_OBJTYPE_CHART: xDrawObj.reset( new XclImpChartObj( rRoot ) ); break;
204 case EXC_OBJTYPE_TEXT: xDrawObj.reset( new XclImpTextObj( rRoot ) ); break;
205 case EXC_OBJTYPE_BUTTON: xDrawObj.reset( new XclImpButtonObj( rRoot ) ); break;
206 case EXC_OBJTYPE_PICTURE: xDrawObj.reset( new XclImpPictureObj( rRoot ) ); break;
207 default:
208 SAL_WARN("sc.filter", "XclImpDrawObjBase::ReadObj3 - unknown object type 0x" << std::hex << nObjType );
209 rRoot.GetTracer().TraceUnsupportedObjects();
213 if (!xDrawObj)
215 xDrawObj.reset(new XclImpPhObj(rRoot));
218 xDrawObj->mnTab = rRoot.GetCurrScTab();
219 xDrawObj->ImplReadObj3( rStrm );
220 return xDrawObj;
223 XclImpDrawObjRef XclImpDrawObjBase::ReadObj4( const XclImpRoot& rRoot, XclImpStream& rStrm )
225 XclImpDrawObjRef xDrawObj;
227 if( rStrm.GetRecLeft() >= 30 )
229 sal_uInt16 nObjType;
230 rStrm.Ignore( 4 );
231 nObjType = rStrm.ReaduInt16();
232 switch( nObjType )
234 case EXC_OBJTYPE_GROUP: xDrawObj.reset( new XclImpGroupObj( rRoot ) ); break;
235 case EXC_OBJTYPE_LINE: xDrawObj.reset( new XclImpLineObj( rRoot ) ); break;
236 case EXC_OBJTYPE_RECTANGLE: xDrawObj.reset( new XclImpRectObj( rRoot ) ); break;
237 case EXC_OBJTYPE_OVAL: xDrawObj.reset( new XclImpOvalObj( rRoot ) ); break;
238 case EXC_OBJTYPE_ARC: xDrawObj.reset( new XclImpArcObj( rRoot ) ); break;
239 case EXC_OBJTYPE_CHART: xDrawObj.reset( new XclImpChartObj( rRoot ) ); break;
240 case EXC_OBJTYPE_TEXT: xDrawObj.reset( new XclImpTextObj( rRoot ) ); break;
241 case EXC_OBJTYPE_BUTTON: xDrawObj.reset( new XclImpButtonObj( rRoot ) ); break;
242 case EXC_OBJTYPE_PICTURE: xDrawObj.reset( new XclImpPictureObj( rRoot ) ); break;
243 case EXC_OBJTYPE_POLYGON: xDrawObj.reset( new XclImpPolygonObj( rRoot ) ); break;
244 default:
245 SAL_WARN("sc.filter", "XclImpDrawObjBase::ReadObj4 - unknown object type 0x" << std::hex << nObjType );
246 rRoot.GetTracer().TraceUnsupportedObjects();
250 if (!xDrawObj)
252 xDrawObj.reset(new XclImpPhObj(rRoot));
255 xDrawObj->mnTab = rRoot.GetCurrScTab();
256 xDrawObj->ImplReadObj4( rStrm );
257 return xDrawObj;
260 XclImpDrawObjRef XclImpDrawObjBase::ReadObj5( const XclImpRoot& rRoot, XclImpStream& rStrm )
262 XclImpDrawObjRef xDrawObj;
264 if( rStrm.GetRecLeft() >= 34 )
266 sal_uInt16 nObjType(EXC_OBJTYPE_UNKNOWN);
267 rStrm.Ignore( 4 );
268 nObjType = rStrm.ReaduInt16();
269 switch( nObjType )
271 case EXC_OBJTYPE_GROUP: xDrawObj.reset( new XclImpGroupObj( rRoot ) ); break;
272 case EXC_OBJTYPE_LINE: xDrawObj.reset( new XclImpLineObj( rRoot ) ); break;
273 case EXC_OBJTYPE_RECTANGLE: xDrawObj.reset( new XclImpRectObj( rRoot ) ); break;
274 case EXC_OBJTYPE_OVAL: xDrawObj.reset( new XclImpOvalObj( rRoot ) ); break;
275 case EXC_OBJTYPE_ARC: xDrawObj.reset( new XclImpArcObj( rRoot ) ); break;
276 case EXC_OBJTYPE_CHART: xDrawObj.reset( new XclImpChartObj( rRoot ) ); break;
277 case EXC_OBJTYPE_TEXT: xDrawObj.reset( new XclImpTextObj( rRoot ) ); break;
278 case EXC_OBJTYPE_BUTTON: xDrawObj.reset( new XclImpButtonObj( rRoot ) ); break;
279 case EXC_OBJTYPE_PICTURE: xDrawObj.reset( new XclImpPictureObj( rRoot ) ); break;
280 case EXC_OBJTYPE_POLYGON: xDrawObj.reset( new XclImpPolygonObj( rRoot ) ); break;
281 case EXC_OBJTYPE_CHECKBOX: xDrawObj.reset( new XclImpCheckBoxObj( rRoot ) ); break;
282 case EXC_OBJTYPE_OPTIONBUTTON: xDrawObj.reset( new XclImpOptionButtonObj( rRoot ) ); break;
283 case EXC_OBJTYPE_EDIT: xDrawObj.reset( new XclImpEditObj( rRoot ) ); break;
284 case EXC_OBJTYPE_LABEL: xDrawObj.reset( new XclImpLabelObj( rRoot ) ); break;
285 case EXC_OBJTYPE_DIALOG: xDrawObj.reset( new XclImpDialogObj( rRoot ) ); break;
286 case EXC_OBJTYPE_SPIN: xDrawObj.reset( new XclImpSpinButtonObj( rRoot ) ); break;
287 case EXC_OBJTYPE_SCROLLBAR: xDrawObj.reset( new XclImpScrollBarObj( rRoot ) ); break;
288 case EXC_OBJTYPE_LISTBOX: xDrawObj.reset( new XclImpListBoxObj( rRoot ) ); break;
289 case EXC_OBJTYPE_GROUPBOX: xDrawObj.reset( new XclImpGroupBoxObj( rRoot ) ); break;
290 case EXC_OBJTYPE_DROPDOWN: xDrawObj.reset( new XclImpDropDownObj( rRoot ) ); break;
291 default:
292 SAL_WARN("sc.filter", "XclImpDrawObjBase::ReadObj5 - unknown object type 0x" << std::hex << nObjType );
293 rRoot.GetTracer().TraceUnsupportedObjects();
294 xDrawObj.reset( new XclImpPhObj( rRoot ) );
298 OSL_ENSURE(xDrawObj, "object import failed");
300 if (xDrawObj)
302 xDrawObj->mnTab = rRoot.GetCurrScTab();
303 xDrawObj->ImplReadObj5( rStrm );
305 return xDrawObj;
308 XclImpDrawObjRef XclImpDrawObjBase::ReadObj8( const XclImpRoot& rRoot, XclImpStream& rStrm )
310 XclImpDrawObjRef xDrawObj;
312 if( rStrm.GetRecLeft() >= 10 )
314 sal_uInt16 nSubRecId(0), nSubRecSize(0), nObjType(0);
315 nSubRecId = rStrm.ReaduInt16();
316 nSubRecSize = rStrm.ReaduInt16();
317 nObjType = rStrm.ReaduInt16();
318 OSL_ENSURE( nSubRecId == EXC_ID_OBJCMO, "XclImpDrawObjBase::ReadObj8 - OBJCMO subrecord expected" );
319 if( (nSubRecId == EXC_ID_OBJCMO) && (nSubRecSize >= 6) )
321 switch( nObjType )
323 // in BIFF8, all simple objects support text
324 case EXC_OBJTYPE_LINE:
325 case EXC_OBJTYPE_ARC:
326 xDrawObj.reset( new XclImpTextObj( rRoot ) );
327 // lines and arcs may be 2-dimensional
328 xDrawObj->SetAreaObj( false );
329 break;
331 // in BIFF8, all simple objects support text
332 case EXC_OBJTYPE_RECTANGLE:
333 case EXC_OBJTYPE_OVAL:
334 case EXC_OBJTYPE_POLYGON:
335 case EXC_OBJTYPE_DRAWING:
336 case EXC_OBJTYPE_TEXT:
337 xDrawObj.reset( new XclImpTextObj( rRoot ) );
338 break;
340 case EXC_OBJTYPE_GROUP: xDrawObj.reset( new XclImpGroupObj( rRoot ) ); break;
341 case EXC_OBJTYPE_CHART: xDrawObj.reset( new XclImpChartObj( rRoot ) ); break;
342 case EXC_OBJTYPE_BUTTON: xDrawObj.reset( new XclImpButtonObj( rRoot ) ); break;
343 case EXC_OBJTYPE_PICTURE: xDrawObj.reset( new XclImpPictureObj( rRoot ) ); break;
344 case EXC_OBJTYPE_CHECKBOX: xDrawObj.reset( new XclImpCheckBoxObj( rRoot ) ); break;
345 case EXC_OBJTYPE_OPTIONBUTTON: xDrawObj.reset( new XclImpOptionButtonObj( rRoot ) ); break;
346 case EXC_OBJTYPE_EDIT: xDrawObj.reset( new XclImpEditObj( rRoot ) ); break;
347 case EXC_OBJTYPE_LABEL: xDrawObj.reset( new XclImpLabelObj( rRoot ) ); break;
348 case EXC_OBJTYPE_DIALOG: xDrawObj.reset( new XclImpDialogObj( rRoot ) ); break;
349 case EXC_OBJTYPE_SPIN: xDrawObj.reset( new XclImpSpinButtonObj( rRoot ) ); break;
350 case EXC_OBJTYPE_SCROLLBAR: xDrawObj.reset( new XclImpScrollBarObj( rRoot ) ); break;
351 case EXC_OBJTYPE_LISTBOX: xDrawObj.reset( new XclImpListBoxObj( rRoot ) ); break;
352 case EXC_OBJTYPE_GROUPBOX: xDrawObj.reset( new XclImpGroupBoxObj( rRoot ) ); break;
353 case EXC_OBJTYPE_DROPDOWN: xDrawObj.reset( new XclImpDropDownObj( rRoot ) ); break;
354 case EXC_OBJTYPE_NOTE: xDrawObj.reset( new XclImpNoteObj( rRoot ) ); break;
356 default:
357 SAL_WARN("sc.filter", "XclImpDrawObjBase::ReadObj8 - unknown object type 0x" << std::hex << nObjType );
358 rRoot.GetTracer().TraceUnsupportedObjects();
363 if (!xDrawObj) //ensure placeholder for unknown or broken records
365 SAL_WARN( "sc.filter", "XclImpDrawObjBase::ReadObj8 import failed, substituting placeholder");
366 xDrawObj.reset( new XclImpPhObj( rRoot ) );
369 xDrawObj->mnTab = rRoot.GetCurrScTab();
370 xDrawObj->ImplReadObj8( rStrm );
371 return xDrawObj;
374 void XclImpDrawObjBase::SetAnchor( const XclObjAnchor& rAnchor )
376 maAnchor = rAnchor;
377 mbHasAnchor = true;
380 void XclImpDrawObjBase::SetDffData(
381 const DffObjData& rDffObjData, const OUString& rObjName, const OUString& rHyperlink,
382 bool bVisible, bool bAutoMargin )
384 mnDffShapeId = rDffObjData.nShapeId;
385 mnDffFlags = rDffObjData.nSpFlags;
386 maObjName = rObjName;
387 maHyperlink = rHyperlink;
388 mbVisible = bVisible;
389 mbAutoMargin = bAutoMargin;
392 OUString XclImpDrawObjBase::GetObjName() const
394 /* #i51348# Always return a non-empty name. Create English
395 default names depending on the object type. This is not implemented as
396 virtual functions in derived classes, as class type and object type may
397 not match. */
398 return maObjName.isEmpty() ? GetObjectManager().GetDefaultObjName(*this) : maObjName;
401 const XclObjAnchor* XclImpDrawObjBase::GetAnchor() const
403 return mbHasAnchor ? &maAnchor : nullptr;
406 bool XclImpDrawObjBase::IsValidSize( const tools::Rectangle& rAnchorRect ) const
408 // XclObjAnchor rounds up the width, width of 3 is the result of an Excel width of 0
409 return mbAreaObj ?
410 ((rAnchorRect.GetWidth() > 3) && (rAnchorRect.GetHeight() > 1)) :
411 ((rAnchorRect.GetWidth() > 3) || (rAnchorRect.GetHeight() > 1));
414 ScRange XclImpDrawObjBase::GetUsedArea( SCTAB nScTab ) const
416 ScRange aScUsedArea( ScAddress::INITIALIZE_INVALID );
417 // #i44077# object inserted -> update used area for OLE object import
418 if( mbHasAnchor && GetAddressConverter().ConvertRange( aScUsedArea, maAnchor, nScTab, nScTab, false ) )
420 // reduce range, if object ends directly on borders between two columns or rows
421 if( (maAnchor.mnRX == 0) && (aScUsedArea.aStart.Col() < aScUsedArea.aEnd.Col()) )
422 aScUsedArea.aEnd.IncCol( -1 );
423 if( (maAnchor.mnBY == 0) && (aScUsedArea.aStart.Row() < aScUsedArea.aEnd.Row()) )
424 aScUsedArea.aEnd.IncRow( -1 );
426 return aScUsedArea;
429 std::size_t XclImpDrawObjBase::GetProgressSize() const
431 return DoGetProgressSize();
434 SdrObjectUniquePtr XclImpDrawObjBase::CreateSdrObject( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect, bool bIsDff ) const
436 SdrObjectUniquePtr xSdrObj;
437 if( bIsDff && !mbCustomDff )
439 rDffConv.Progress( GetProgressSize() );
441 else
443 xSdrObj = DoCreateSdrObj( rDffConv, rAnchorRect );
445 //added for exporting OCX control
446 /* mnObjType value set should be as below table:
447 0x0000 Group 0x0001 Line
448 0x0002 Rectangle 0x0003 Oval
449 0x0004 Arc 0x0005 Chart
450 0x0006 Text 0x0009 Polygon
451 +-----------------------------------------------------+
452 OCX ==>| 0x0008 Picture |
453 +-----------------------------------------------------+
454 | 0x0007 Button |
455 | 0x000B Checkbox 0x000C Radio button |
456 | 0x000D Edit box 0x000E Label |
457 TBX ==> | 0x000F Dialog box 0x0010 Spin control |
458 | 0x0011 Scrollbar 0x0012 List |
459 | 0x0013 Group box 0x0014 Dropdown list |
460 +-----------------------------------------------------+
461 0x0019 Note 0x001E OfficeArt object
463 if( xSdrObj && xSdrObj->IsUnoObj() &&
464 ( (mnObjType < 25 && mnObjType > 10) || mnObjType == 7 || mnObjType == 8 ) )
466 SdrUnoObj* pSdrUnoObj = dynamic_cast< SdrUnoObj* >( xSdrObj.get() );
467 if( pSdrUnoObj != nullptr )
469 const Reference< XControlModel >& xCtrlModel = pSdrUnoObj->GetUnoControlModel();
470 Reference< XPropertySet > xPropSet(xCtrlModel,UNO_QUERY);
471 const static OUString sPropertyName("ControlTypeinMSO");
473 enum { eCreateFromOffice = 0, eCreateFromMSTBXControl, eCreateFromMSOCXControl };
475 if( mnObjType == 7 || (mnObjType < 25 && mnObjType > 10) )//TBX
477 //Need summary type for export. Detail type(checkbox, button ...) has been contained by mnObjType
478 const sal_Int16 nTBXControlType = eCreateFromMSTBXControl ;
481 xPropSet->setPropertyValue(sPropertyName, Any(nTBXControlType));
483 catch(const Exception&)
485 SAL_WARN("sc.filter", "XclImpDrawObjBase::CreateSdrObject, this control can't be set the property ControlTypeinMSO!");
488 if( mnObjType == 8 )//OCX
490 //Need summary type for export
491 const static OUString sObjIdPropertyName("ObjIDinMSO");
492 const XclImpPictureObj* const pObj = dynamic_cast< const XclImpPictureObj* const >(this);
493 if( pObj != nullptr && pObj->IsOcxControl() )
495 const sal_Int16 nOCXControlType = eCreateFromMSOCXControl;
498 xPropSet->setPropertyValue(sPropertyName, Any(nOCXControlType));
499 //Detail type(checkbox, button ...)
500 xPropSet->setPropertyValue(sObjIdPropertyName, makeAny<sal_uInt16>(mnObjId));
502 catch(const Exception&)
504 SAL_WARN("sc.filter", "XclImpDrawObjBase::CreateSdrObject, this control can't be set the property ObjIDinMSO!");
512 return xSdrObj;
515 void XclImpDrawObjBase::NotifyMacroEventRead()
517 if (mbNotifyMacroEventRead)
518 return;
519 SfxObjectShell* pDocShell = GetDocShell();
520 if (!pDocShell)
521 return;
522 comphelper::DocumentInfo::notifyMacroEventRead(pDocShell->GetModel());
523 mbNotifyMacroEventRead = true;
526 void XclImpDrawObjBase::PreProcessSdrObject( XclImpDffConverter& rDffConv, SdrObject& rSdrObj )
528 // default: front layer, derived classes may have to set other layer in DoPreProcessSdrObj()
529 rSdrObj.NbcSetLayer( SC_LAYER_FRONT );
531 // set object name (GetObjName() will always return a non-empty name)
532 rSdrObj.SetName( GetObjName() );
534 // #i39167# full width for all objects regardless of horizontal alignment
535 rSdrObj.SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_BLOCK ) );
537 // automatic text margin
538 if( mbAutoMargin )
540 sal_Int32 nMargin = rDffConv.GetDefaultTextMargin();
541 rSdrObj.SetMergedItem( makeSdrTextLeftDistItem( nMargin ) );
542 rSdrObj.SetMergedItem( makeSdrTextRightDistItem( nMargin ) );
543 rSdrObj.SetMergedItem( makeSdrTextUpperDistItem( nMargin ) );
544 rSdrObj.SetMergedItem( makeSdrTextLowerDistItem( nMargin ) );
547 // macro and hyperlink
548 // removed oracle/sun check for mbSimpleMacro ( no idea what its for )
549 if (!maMacroName.isEmpty() || !maHyperlink.isEmpty())
551 if( ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( &rSdrObj, true ) )
553 OUString sMacro = XclTools::GetSbMacroUrl(maMacroName, GetDocShell());
554 if (!sMacro.isEmpty())
555 NotifyMacroEventRead();
556 pInfo->SetMacro(sMacro);
557 pInfo->SetHlink( maHyperlink );
561 // call virtual function for object type specific processing
562 DoPreProcessSdrObj( rDffConv, rSdrObj );
565 void XclImpDrawObjBase::PostProcessSdrObject( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const
567 // call virtual function for object type specific processing
568 DoPostProcessSdrObj( rDffConv, rSdrObj );
571 // protected ------------------------------------------------------------------
573 void XclImpDrawObjBase::ReadName5( XclImpStream& rStrm, sal_uInt16 nNameLen )
575 maObjName.clear();
576 if( nNameLen > 0 )
578 // name length field is repeated before the name
579 maObjName = rStrm.ReadByteString( false );
580 // skip padding byte for word boundaries
581 if( rStrm.GetRecPos() & 1 ) rStrm.Ignore( 1 );
585 void XclImpDrawObjBase::ReadMacro3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
587 maMacroName.clear();
588 rStrm.Ignore( nMacroSize );
589 // skip padding byte for word boundaries, not contained in nMacroSize
590 if( rStrm.GetRecPos() & 1 ) rStrm.Ignore( 1 );
593 void XclImpDrawObjBase::ReadMacro4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
595 maMacroName.clear();
596 rStrm.Ignore( nMacroSize );
599 void XclImpDrawObjBase::ReadMacro5( XclImpStream& rStrm, sal_uInt16 nMacroSize )
601 maMacroName.clear();
602 rStrm.Ignore( nMacroSize );
605 void XclImpDrawObjBase::ReadMacro8( XclImpStream& rStrm )
607 maMacroName.clear();
608 if( rStrm.GetRecLeft() > 6 )
610 // macro is stored in a tNameXR token containing a link to a defined name
611 sal_uInt16 nFmlaSize;
612 nFmlaSize = rStrm.ReaduInt16();
613 rStrm.Ignore( 4 );
614 OSL_ENSURE( nFmlaSize == 7, "XclImpDrawObjBase::ReadMacro - unexpected formula size" );
615 if( nFmlaSize == 7 )
617 sal_uInt8 nTokenId;
618 sal_uInt16 nExtSheet, nExtName;
619 nTokenId = rStrm.ReaduInt8();
620 nExtSheet = rStrm.ReaduInt16();
621 nExtName = rStrm.ReaduInt16();
622 OSL_ENSURE( nTokenId == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ),
623 "XclImpDrawObjBase::ReadMacro - tNameXR token expected" );
624 if( nTokenId == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ) )
625 maMacroName = GetLinkManager().GetMacroName( nExtSheet, nExtName );
630 void XclImpDrawObjBase::ConvertLineStyle( SdrObject& rSdrObj, const XclObjLineData& rLineData ) const
632 if( rLineData.IsAuto() )
634 XclObjLineData aAutoData;
635 aAutoData.mnAuto = 0;
636 ConvertLineStyle( rSdrObj, aAutoData );
638 else
640 long nLineWidth = 35 * ::std::min( rLineData.mnWidth, EXC_OBJ_LINE_THICK );
641 rSdrObj.SetMergedItem( XLineWidthItem( nLineWidth ) );
642 rSdrObj.SetMergedItem( XLineColorItem( EMPTY_OUSTRING, GetPalette().GetColor( rLineData.mnColorIdx ) ) );
643 rSdrObj.SetMergedItem( XLineJointItem( css::drawing::LineJoint_MITER ) );
645 sal_uLong nDotLen = ::std::max< sal_uLong >( 70 * rLineData.mnWidth, 35 );
646 sal_uLong nDashLen = 3 * nDotLen;
647 sal_uLong nDist = 2 * nDotLen;
649 switch( rLineData.mnStyle )
651 default:
652 case EXC_OBJ_LINE_SOLID:
653 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_SOLID ) );
654 break;
655 case EXC_OBJ_LINE_DASH:
656 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_DASH ) );
657 rSdrObj.SetMergedItem( XLineDashItem( EMPTY_OUSTRING, XDash( css::drawing::DashStyle_RECT, 0, nDotLen, 1, nDashLen, nDist ) ) );
658 break;
659 case EXC_OBJ_LINE_DOT:
660 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_DASH ) );
661 rSdrObj.SetMergedItem( XLineDashItem( EMPTY_OUSTRING, XDash( css::drawing::DashStyle_RECT, 1, nDotLen, 0, nDashLen, nDist ) ) );
662 break;
663 case EXC_OBJ_LINE_DASHDOT:
664 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_DASH ) );
665 rSdrObj.SetMergedItem( XLineDashItem( EMPTY_OUSTRING, XDash( css::drawing::DashStyle_RECT, 1, nDotLen, 1, nDashLen, nDist ) ) );
666 break;
667 case EXC_OBJ_LINE_DASHDOTDOT:
668 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_DASH ) );
669 rSdrObj.SetMergedItem( XLineDashItem( EMPTY_OUSTRING, XDash( css::drawing::DashStyle_RECT, 2, nDotLen, 1, nDashLen, nDist ) ) );
670 break;
671 case EXC_OBJ_LINE_MEDTRANS:
672 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_SOLID ) );
673 rSdrObj.SetMergedItem( XLineTransparenceItem( 50 ) );
674 break;
675 case EXC_OBJ_LINE_DARKTRANS:
676 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_SOLID ) );
677 rSdrObj.SetMergedItem( XLineTransparenceItem( 25 ) );
678 break;
679 case EXC_OBJ_LINE_LIGHTTRANS:
680 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_SOLID ) );
681 rSdrObj.SetMergedItem( XLineTransparenceItem( 75 ) );
682 break;
683 case EXC_OBJ_LINE_NONE:
684 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_NONE ) );
685 break;
690 void XclImpDrawObjBase::ConvertFillStyle( SdrObject& rSdrObj, const XclObjFillData& rFillData ) const
692 if( rFillData.IsAuto() )
694 XclObjFillData aAutoData;
695 aAutoData.mnAuto = 0;
696 ConvertFillStyle( rSdrObj, aAutoData );
698 else if( rFillData.mnPattern == EXC_PATT_NONE )
700 rSdrObj.SetMergedItem( XFillStyleItem( drawing::FillStyle_NONE ) );
702 else
704 Color aPattColor = GetPalette().GetColor( rFillData.mnPattColorIdx );
705 Color aBackColor = GetPalette().GetColor( rFillData.mnBackColorIdx );
706 if( (rFillData.mnPattern == EXC_PATT_SOLID) || (aPattColor == aBackColor) )
708 rSdrObj.SetMergedItem( XFillStyleItem( drawing::FillStyle_SOLID ) );
709 rSdrObj.SetMergedItem( XFillColorItem( EMPTY_OUSTRING, aPattColor ) );
711 else
713 static const sal_uInt8 sppnPatterns[][ 8 ] =
715 { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 },
716 { 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD },
717 { 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 },
718 { 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00 },
719 { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC },
720 { 0x33, 0x66, 0xCC, 0x99, 0x33, 0x66, 0xCC, 0x99 },
721 { 0xCC, 0x66, 0x33, 0x99, 0xCC, 0x66, 0x33, 0x99 },
722 { 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33 },
723 { 0xCC, 0xFF, 0x33, 0xFF, 0xCC, 0xFF, 0x33, 0xFF },
724 { 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 },
725 { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 },
726 { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 },
727 { 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 },
728 { 0xFF, 0x11, 0x11, 0x11, 0xFF, 0x11, 0x11, 0x11 },
729 { 0xAA, 0x44, 0xAA, 0x11, 0xAA, 0x44, 0xAA, 0x11 },
730 { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 },
731 { 0x80, 0x00, 0x08, 0x00, 0x80, 0x00, 0x08, 0x00 }
733 const sal_uInt8* const pnPattern = sppnPatterns[std::min<size_t>(rFillData.mnPattern - 2, SAL_N_ELEMENTS(sppnPatterns) - 1)];
734 // create 2-colored 8x8 DIB
735 SvMemoryStream aMemStrm;
736 aMemStrm.WriteUInt32( 12 ).WriteInt16( 8 ).WriteInt16( 8 ).WriteUInt16( 1 ).WriteUInt16( 1 );
737 aMemStrm.WriteUChar( 0xFF ).WriteUChar( 0xFF ).WriteUChar( 0xFF );
738 aMemStrm.WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x00 );
739 for( size_t nIdx = 0; nIdx < 8; ++nIdx )
740 aMemStrm.WriteUInt32( pnPattern[ nIdx ] ); // 32-bit little-endian
741 aMemStrm.Seek( STREAM_SEEK_TO_BEGIN );
742 Bitmap aBitmap;
743 ReadDIB(aBitmap, aMemStrm, false);
745 XOBitmap aXOBitmap(( BitmapEx(aBitmap) ));
746 aXOBitmap.Bitmap2Array();
747 if( aXOBitmap.GetBackgroundColor() == COL_BLACK )
748 ::std::swap( aPattColor, aBackColor );
749 aXOBitmap.SetPixelColor( aPattColor );
750 aXOBitmap.SetBackgroundColor( aBackColor );
751 aXOBitmap.Array2Bitmap();
752 aBitmap = aXOBitmap.GetBitmap().GetBitmapRef();
754 rSdrObj.SetMergedItem(XFillStyleItem(drawing::FillStyle_BITMAP));
755 rSdrObj.SetMergedItem(XFillBitmapItem(EMPTY_OUSTRING, Graphic(aBitmap)));
760 void XclImpDrawObjBase::ConvertFrameStyle( SdrObject& rSdrObj, sal_uInt16 nFrameFlags ) const
762 if( ::get_flag( nFrameFlags, EXC_OBJ_FRAME_SHADOW ) )
764 rSdrObj.SetMergedItem( makeSdrShadowItem( true ) );
765 rSdrObj.SetMergedItem( makeSdrShadowXDistItem( 35 ) );
766 rSdrObj.SetMergedItem( makeSdrShadowYDistItem( 35 ) );
767 rSdrObj.SetMergedItem( makeSdrShadowColorItem( GetPalette().GetColor( EXC_COLOR_WINDOWTEXT ) ) );
771 Color XclImpDrawObjBase::GetSolidLineColor( const XclObjLineData& rLineData ) const
773 Color aColor( COL_TRANSPARENT );
774 if( rLineData.IsAuto() )
776 XclObjLineData aAutoData;
777 aAutoData.mnAuto = 0;
778 aColor = GetSolidLineColor( aAutoData );
780 else if( rLineData.mnStyle != EXC_OBJ_LINE_NONE )
782 aColor = GetPalette().GetColor( rLineData.mnColorIdx );
784 return aColor;
787 Color XclImpDrawObjBase::GetSolidFillColor( const XclObjFillData& rFillData ) const
789 Color aColor( COL_TRANSPARENT );
790 if( rFillData.IsAuto() )
792 XclObjFillData aAutoData;
793 aAutoData.mnAuto = 0;
794 aColor = GetSolidFillColor( aAutoData );
796 else if( rFillData.mnPattern != EXC_PATT_NONE )
798 Color aPattColor = GetPalette().GetColor( rFillData.mnPattColorIdx );
799 Color aBackColor = GetPalette().GetColor( rFillData.mnBackColorIdx );
800 aColor = XclTools::GetPatternColor( aPattColor, aBackColor, rFillData.mnPattern );
802 return aColor;
805 void XclImpDrawObjBase::DoReadObj3( XclImpStream&, sal_uInt16 )
809 void XclImpDrawObjBase::DoReadObj4( XclImpStream&, sal_uInt16 )
813 void XclImpDrawObjBase::DoReadObj5( XclImpStream&, sal_uInt16, sal_uInt16 )
817 void XclImpDrawObjBase::DoReadObj8SubRec( XclImpStream&, sal_uInt16, sal_uInt16 )
821 std::size_t XclImpDrawObjBase::DoGetProgressSize() const
823 return 1;
826 SdrObjectUniquePtr XclImpDrawObjBase::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& ) const
828 rDffConv.Progress( GetProgressSize() );
829 return nullptr;
832 void XclImpDrawObjBase::DoPreProcessSdrObj( XclImpDffConverter&, SdrObject& ) const
834 // trace if object is not printable
835 if( !IsPrintable() )
836 GetTracer().TraceObjectNotPrintable();
839 void XclImpDrawObjBase::DoPostProcessSdrObj( XclImpDffConverter&, SdrObject& ) const
843 void XclImpDrawObjBase::ImplReadObj3( XclImpStream& rStrm )
845 // back to offset 4 (ignore object count field)
846 rStrm.Seek( 4 );
848 sal_uInt16 nObjFlags, nMacroSize;
849 mnObjType = rStrm.ReaduInt16();
850 mnObjId = rStrm.ReaduInt16();
851 nObjFlags = rStrm.ReaduInt16();
852 rStrm >> maAnchor;
853 nMacroSize = rStrm.ReaduInt16();
854 rStrm.Ignore( 2 );
856 mbHasAnchor = true;
857 mbHidden = ::get_flag( nObjFlags, EXC_OBJ_HIDDEN );
858 mbVisible = ::get_flag( nObjFlags, EXC_OBJ_VISIBLE );
859 DoReadObj3( rStrm, nMacroSize );
862 void XclImpDrawObjBase::ImplReadObj4( XclImpStream& rStrm )
864 // back to offset 4 (ignore object count field)
865 rStrm.Seek( 4 );
867 sal_uInt16 nObjFlags, nMacroSize;
868 mnObjType = rStrm.ReaduInt16();
869 mnObjId = rStrm.ReaduInt16();
870 nObjFlags = rStrm.ReaduInt16();
871 rStrm >> maAnchor;
872 nMacroSize = rStrm.ReaduInt16();
873 rStrm.Ignore( 2 );
875 mbHasAnchor = true;
876 mbHidden = ::get_flag( nObjFlags, EXC_OBJ_HIDDEN );
877 mbVisible = ::get_flag( nObjFlags, EXC_OBJ_VISIBLE );
878 mbPrintable = ::get_flag( nObjFlags, EXC_OBJ_PRINTABLE );
879 DoReadObj4( rStrm, nMacroSize );
882 void XclImpDrawObjBase::ImplReadObj5( XclImpStream& rStrm )
884 // back to offset 4 (ignore object count field)
885 rStrm.Seek( 4 );
887 sal_uInt16 nObjFlags, nMacroSize, nNameLen;
888 mnObjType = rStrm.ReaduInt16();
889 mnObjId = rStrm.ReaduInt16();
890 nObjFlags = rStrm.ReaduInt16();
891 rStrm >> maAnchor;
892 nMacroSize = rStrm.ReaduInt16();
893 rStrm.Ignore( 2 );
894 nNameLen = rStrm.ReaduInt16();
895 rStrm.Ignore( 2 );
897 mbHasAnchor = true;
898 mbHidden = ::get_flag( nObjFlags, EXC_OBJ_HIDDEN );
899 mbVisible = ::get_flag( nObjFlags, EXC_OBJ_VISIBLE );
900 mbPrintable = ::get_flag( nObjFlags, EXC_OBJ_PRINTABLE );
901 DoReadObj5( rStrm, nNameLen, nMacroSize );
904 void XclImpDrawObjBase::ImplReadObj8( XclImpStream& rStrm )
906 // back to beginning
907 rStrm.Seek( EXC_REC_SEEK_TO_BEGIN );
909 bool bLoop = true;
910 while( bLoop && (rStrm.GetRecLeft() >= 4) )
912 sal_uInt16 nSubRecId, nSubRecSize;
913 nSubRecId = rStrm.ReaduInt16();
914 nSubRecSize = rStrm.ReaduInt16();
915 rStrm.PushPosition();
916 // sometimes the last subrecord has an invalid length (OBJLBSDATA) -> min()
917 nSubRecSize = static_cast< sal_uInt16 >( ::std::min< std::size_t >( nSubRecSize, rStrm.GetRecLeft() ) );
919 switch( nSubRecId )
921 case EXC_ID_OBJCMO:
922 OSL_ENSURE( rStrm.GetRecPos() == 4, "XclImpDrawObjBase::ImplReadObj8 - unexpected OBJCMO subrecord" );
923 if( (rStrm.GetRecPos() == 4) && (nSubRecSize >= 6) )
925 sal_uInt16 nObjFlags;
926 mnObjType = rStrm.ReaduInt16();
927 mnObjId = rStrm.ReaduInt16( );
928 nObjFlags = rStrm.ReaduInt16( );
929 mbPrintable = ::get_flag( nObjFlags, EXC_OBJCMO_PRINTABLE );
931 break;
932 case EXC_ID_OBJMACRO:
933 ReadMacro8( rStrm );
934 break;
935 case EXC_ID_OBJEND:
936 bLoop = false;
937 break;
938 default:
939 DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
942 rStrm.PopPosition();
943 rStrm.Ignore( nSubRecSize );
946 /* Call DoReadObj8SubRec() with EXC_ID_OBJEND for further stream
947 processing (e.g. charts), even if the OBJEND subrecord is missing. */
948 DoReadObj8SubRec( rStrm, EXC_ID_OBJEND, 0 );
950 /* Pictures that Excel reads from BIFF5 and writes to BIFF8 still have the
951 IMGDATA record following the OBJ record (but they use the image data
952 stored in DFF). The IMGDATA record may be continued by several CONTINUE
953 records. But the last CONTINUE record may be in fact an MSODRAWING
954 record that contains the DFF data of the next drawing object! So we
955 have to skip just enough CONTINUE records to look at the next
956 MSODRAWING/CONTINUE record. */
957 if( (rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord() )
959 sal_uInt32 nDataSize;
960 rStrm.Ignore( 4 );
961 nDataSize = rStrm.ReaduInt32();
962 nDataSize -= rStrm.GetRecLeft();
963 // skip following CONTINUE records until IMGDATA ends
964 while( (nDataSize > 0) && (rStrm.GetNextRecId() == EXC_ID_CONT) && rStrm.StartNextRecord() )
966 OSL_ENSURE( nDataSize >= rStrm.GetRecLeft(), "XclImpDrawObjBase::ImplReadObj8 - CONTINUE too long" );
967 nDataSize -= ::std::min< sal_uInt32 >( rStrm.GetRecLeft(), nDataSize );
969 OSL_ENSURE( nDataSize == 0, "XclImpDrawObjBase::ImplReadObj8 - missing CONTINUE records" );
970 // next record may be MSODRAWING or CONTINUE or anything else
974 void XclImpDrawObjVector::InsertGrouped( XclImpDrawObjRef const & xDrawObj )
976 if( !mObjs.empty() )
977 if( XclImpGroupObj* pGroupObj = dynamic_cast< XclImpGroupObj* >( mObjs.back().get() ) )
978 if( pGroupObj->TryInsert( xDrawObj ) )
979 return;
980 mObjs.push_back( xDrawObj );
983 std::size_t XclImpDrawObjVector::GetProgressSize() const
985 return std::accumulate(mObjs.begin(), mObjs.end(), std::size_t(0),
986 [](const std::size_t& rSum, const XclImpDrawObjRef& rxObj) { return rSum + rxObj->GetProgressSize(); });
989 XclImpPhObj::XclImpPhObj( const XclImpRoot& rRoot ) :
990 XclImpDrawObjBase( rRoot )
992 SetProcessSdrObj( false );
995 XclImpGroupObj::XclImpGroupObj( const XclImpRoot& rRoot ) :
996 XclImpDrawObjBase( rRoot ),
997 mnFirstUngrouped( 0 )
1001 bool XclImpGroupObj::TryInsert( XclImpDrawObjRef const & xDrawObj )
1003 if( xDrawObj->GetObjId() == mnFirstUngrouped )
1004 return false;
1005 // insert into own list or into nested group
1006 maChildren.InsertGrouped( xDrawObj );
1007 return true;
1010 void XclImpGroupObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1012 rStrm.Ignore( 4 );
1013 mnFirstUngrouped = rStrm.ReaduInt16();
1014 rStrm.Ignore( 16 );
1015 ReadMacro3( rStrm, nMacroSize );
1018 void XclImpGroupObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1020 rStrm.Ignore( 4 );
1021 mnFirstUngrouped = rStrm.ReaduInt16();
1022 rStrm.Ignore( 16 );
1023 ReadMacro4( rStrm, nMacroSize );
1026 void XclImpGroupObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1028 rStrm.Ignore( 4 );
1029 mnFirstUngrouped = rStrm.ReaduInt16();
1030 rStrm.Ignore( 16 );
1031 ReadName5( rStrm, nNameLen );
1032 ReadMacro5( rStrm, nMacroSize );
1035 std::size_t XclImpGroupObj::DoGetProgressSize() const
1037 return XclImpDrawObjBase::DoGetProgressSize() + maChildren.GetProgressSize();
1040 SdrObjectUniquePtr XclImpGroupObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& /*rAnchorRect*/ ) const
1042 std::unique_ptr<SdrObjGroup, SdrObjectFreeOp> xSdrObj(
1043 new SdrObjGroup(
1044 *GetDoc().GetDrawLayer()));
1045 // child objects in BIFF2-BIFF5 have absolute size, not needed to pass own anchor rectangle
1046 SdrObjList& rObjList = *xSdrObj->GetSubList(); // SdrObjGroup always returns existing sublist
1047 for( const auto& rxChild : maChildren )
1048 rDffConv.ProcessObject( rObjList, *rxChild );
1049 rDffConv.Progress();
1050 return xSdrObj;
1053 XclImpLineObj::XclImpLineObj( const XclImpRoot& rRoot ) :
1054 XclImpDrawObjBase( rRoot ),
1055 mnArrows( 0 ),
1056 mnStartPoint( EXC_OBJ_LINE_TL )
1058 SetAreaObj( false );
1061 void XclImpLineObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1063 rStrm >> maLineData;
1064 mnArrows = rStrm.ReaduInt16();
1065 mnStartPoint = rStrm.ReaduInt8();
1066 rStrm.Ignore( 1 );
1067 ReadMacro3( rStrm, nMacroSize );
1070 void XclImpLineObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1072 rStrm >> maLineData;
1073 mnArrows = rStrm.ReaduInt16();
1074 mnStartPoint = rStrm.ReaduInt8();
1075 rStrm.Ignore( 1 );
1076 ReadMacro4( rStrm, nMacroSize );
1079 void XclImpLineObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1081 rStrm >> maLineData;
1082 mnArrows = rStrm.ReaduInt16();
1083 mnStartPoint = rStrm.ReaduInt8();
1084 rStrm.Ignore( 1 );
1085 ReadName5( rStrm, nNameLen );
1086 ReadMacro5( rStrm, nMacroSize );
1089 SdrObjectUniquePtr XclImpLineObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1091 ::basegfx::B2DPolygon aB2DPolygon;
1092 switch( mnStartPoint )
1094 default:
1095 case EXC_OBJ_LINE_TL:
1096 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Top() ) );
1097 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Bottom() ) );
1098 break;
1099 case EXC_OBJ_LINE_TR:
1100 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Top() ) );
1101 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Bottom() ) );
1102 break;
1103 case EXC_OBJ_LINE_BR:
1104 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Bottom() ) );
1105 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Top() ) );
1106 break;
1107 case EXC_OBJ_LINE_BL:
1108 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Bottom() ) );
1109 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Top() ) );
1110 break;
1112 SdrObjectUniquePtr xSdrObj(
1113 new SdrPathObj(
1114 *GetDoc().GetDrawLayer(),
1115 OBJ_LINE,
1116 ::basegfx::B2DPolyPolygon(aB2DPolygon)));
1117 ConvertLineStyle( *xSdrObj, maLineData );
1119 // line ends
1120 sal_uInt8 nArrowType = ::extract_value< sal_uInt8 >( mnArrows, 0, 4 );
1121 bool bLineStart = false;
1122 bool bLineEnd = false;
1123 bool bFilled = false;
1124 switch( nArrowType )
1126 case EXC_OBJ_ARROW_OPEN: bLineStart = false; bLineEnd = true; bFilled = false; break;
1127 case EXC_OBJ_ARROW_OPENBOTH: bLineStart = true; bLineEnd = true; bFilled = false; break;
1128 case EXC_OBJ_ARROW_FILLED: bLineStart = false; bLineEnd = true; bFilled = true; break;
1129 case EXC_OBJ_ARROW_FILLEDBOTH: bLineStart = true; bLineEnd = true; bFilled = true; break;
1131 if( bLineStart || bLineEnd )
1133 sal_uInt8 nArrowWidth = ::extract_value< sal_uInt8 >( mnArrows, 4, 4 );
1134 double fArrowWidth = 3.0;
1135 switch( nArrowWidth )
1137 case EXC_OBJ_ARROW_NARROW: fArrowWidth = 2.0; break;
1138 case EXC_OBJ_ARROW_MEDIUM: fArrowWidth = 3.0; break;
1139 case EXC_OBJ_ARROW_WIDE: fArrowWidth = 5.0; break;
1142 sal_uInt8 nArrowLength = ::extract_value< sal_uInt8 >( mnArrows, 8, 4 );
1143 double fArrowLength = 3.0;
1144 switch( nArrowLength )
1146 case EXC_OBJ_ARROW_NARROW: fArrowLength = 2.5; break;
1147 case EXC_OBJ_ARROW_MEDIUM: fArrowLength = 3.5; break;
1148 case EXC_OBJ_ARROW_WIDE: fArrowLength = 6.0; break;
1151 ::basegfx::B2DPolygon aArrowPoly;
1152 #define EXC_ARROW_POINT( x, y ) ::basegfx::B2DPoint( fArrowWidth * (x), fArrowLength * (y) )
1153 if( bFilled )
1155 aArrowPoly.append( EXC_ARROW_POINT( 0, 100 ) );
1156 aArrowPoly.append( EXC_ARROW_POINT( 50, 0 ) );
1157 aArrowPoly.append( EXC_ARROW_POINT( 100, 100 ) );
1159 else
1161 sal_uInt8 nLineWidth = ::limit_cast< sal_uInt8 >( maLineData.mnWidth, EXC_OBJ_LINE_THIN, EXC_OBJ_LINE_THICK );
1162 aArrowPoly.append( EXC_ARROW_POINT( 50, 0 ) );
1163 aArrowPoly.append( EXC_ARROW_POINT( 100, 100 - 3 * nLineWidth ) );
1164 aArrowPoly.append( EXC_ARROW_POINT( 100 - 5 * nLineWidth, 100 ) );
1165 aArrowPoly.append( EXC_ARROW_POINT( 50, 12 * nLineWidth ) );
1166 aArrowPoly.append( EXC_ARROW_POINT( 5 * nLineWidth, 100 ) );
1167 aArrowPoly.append( EXC_ARROW_POINT( 0, 100 - 3 * nLineWidth ) );
1169 #undef EXC_ARROW_POINT
1171 ::basegfx::B2DPolyPolygon aArrowPolyPoly( aArrowPoly );
1172 long nWidth = static_cast< long >( 125 * fArrowWidth );
1173 if( bLineStart )
1175 xSdrObj->SetMergedItem( XLineStartItem( EMPTY_OUSTRING, aArrowPolyPoly ) );
1176 xSdrObj->SetMergedItem( XLineStartWidthItem( nWidth ) );
1177 xSdrObj->SetMergedItem( XLineStartCenterItem( false ) );
1179 if( bLineEnd )
1181 xSdrObj->SetMergedItem( XLineEndItem( EMPTY_OUSTRING, aArrowPolyPoly ) );
1182 xSdrObj->SetMergedItem( XLineEndWidthItem( nWidth ) );
1183 xSdrObj->SetMergedItem( XLineEndCenterItem( false ) );
1186 rDffConv.Progress();
1187 return xSdrObj;
1190 XclImpRectObj::XclImpRectObj( const XclImpRoot& rRoot ) :
1191 XclImpDrawObjBase( rRoot ),
1192 mnFrameFlags( 0 )
1194 SetAreaObj( true );
1197 void XclImpRectObj::ReadFrameData( XclImpStream& rStrm )
1199 rStrm >> maFillData >> maLineData;
1200 mnFrameFlags = rStrm.ReaduInt16();
1203 void XclImpRectObj::ConvertRectStyle( SdrObject& rSdrObj ) const
1205 ConvertLineStyle( rSdrObj, maLineData );
1206 ConvertFillStyle( rSdrObj, maFillData );
1207 ConvertFrameStyle( rSdrObj, mnFrameFlags );
1210 void XclImpRectObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1212 ReadFrameData( rStrm );
1213 ReadMacro3( rStrm, nMacroSize );
1216 void XclImpRectObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1218 ReadFrameData( rStrm );
1219 ReadMacro4( rStrm, nMacroSize );
1222 void XclImpRectObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1224 ReadFrameData( rStrm );
1225 ReadName5( rStrm, nNameLen );
1226 ReadMacro5( rStrm, nMacroSize );
1229 SdrObjectUniquePtr XclImpRectObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1231 SdrObjectUniquePtr xSdrObj(
1232 new SdrRectObj(
1233 *GetDoc().GetDrawLayer(),
1234 rAnchorRect));
1235 ConvertRectStyle( *xSdrObj );
1236 rDffConv.Progress();
1237 return xSdrObj;
1240 XclImpOvalObj::XclImpOvalObj( const XclImpRoot& rRoot ) :
1241 XclImpRectObj( rRoot )
1245 SdrObjectUniquePtr XclImpOvalObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1247 SdrObjectUniquePtr xSdrObj(
1248 new SdrCircObj(
1249 *GetDoc().GetDrawLayer(),
1250 SdrCircKind::Full,
1251 rAnchorRect));
1252 ConvertRectStyle( *xSdrObj );
1253 rDffConv.Progress();
1254 return xSdrObj;
1257 XclImpArcObj::XclImpArcObj( const XclImpRoot& rRoot ) :
1258 XclImpDrawObjBase( rRoot ),
1259 mnQuadrant( EXC_OBJ_ARC_TR )
1261 SetAreaObj( false ); // arc may be 2-dimensional
1264 void XclImpArcObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1266 rStrm >> maFillData >> maLineData;
1267 mnQuadrant = rStrm.ReaduInt8();
1268 rStrm.Ignore( 1 );
1269 ReadMacro3( rStrm, nMacroSize );
1272 void XclImpArcObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1274 rStrm >> maFillData >> maLineData;
1275 mnQuadrant = rStrm.ReaduInt8();
1276 rStrm.Ignore( 1 );
1277 ReadMacro4( rStrm, nMacroSize );
1280 void XclImpArcObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1282 rStrm >> maFillData >> maLineData;
1283 mnQuadrant = rStrm.ReaduInt8();
1284 rStrm.Ignore( 1 );
1285 ReadName5( rStrm, nNameLen );
1286 ReadMacro5( rStrm, nMacroSize );
1289 SdrObjectUniquePtr XclImpArcObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1291 tools::Rectangle aNewRect = rAnchorRect;
1292 long nStartAngle = 0;
1293 long nEndAngle = 0;
1294 switch( mnQuadrant )
1296 default:
1297 case EXC_OBJ_ARC_TR:
1298 nStartAngle = 0;
1299 nEndAngle = 9000;
1300 aNewRect.AdjustLeft( -(rAnchorRect.GetWidth()) );
1301 aNewRect.AdjustBottom(rAnchorRect.GetHeight() );
1302 break;
1303 case EXC_OBJ_ARC_TL:
1304 nStartAngle = 9000;
1305 nEndAngle = 18000;
1306 aNewRect.AdjustRight(rAnchorRect.GetWidth() );
1307 aNewRect.AdjustBottom(rAnchorRect.GetHeight() );
1308 break;
1309 case EXC_OBJ_ARC_BL:
1310 nStartAngle = 18000;
1311 nEndAngle = 27000;
1312 aNewRect.AdjustRight(rAnchorRect.GetWidth() );
1313 aNewRect.AdjustTop( -(rAnchorRect.GetHeight()) );
1314 break;
1315 case EXC_OBJ_ARC_BR:
1316 nStartAngle = 27000;
1317 nEndAngle = 0;
1318 aNewRect.AdjustLeft( -(rAnchorRect.GetWidth()) );
1319 aNewRect.AdjustTop( -(rAnchorRect.GetHeight()) );
1320 break;
1322 SdrCircKind eObjKind = maFillData.IsFilled() ? SdrCircKind::Section : SdrCircKind::Arc;
1323 SdrObjectUniquePtr xSdrObj(
1324 new SdrCircObj(
1325 *GetDoc().GetDrawLayer(),
1326 eObjKind,
1327 aNewRect,
1328 nStartAngle,
1329 nEndAngle));
1330 ConvertFillStyle( *xSdrObj, maFillData );
1331 ConvertLineStyle( *xSdrObj, maLineData );
1332 rDffConv.Progress();
1333 return xSdrObj;
1336 XclImpPolygonObj::XclImpPolygonObj( const XclImpRoot& rRoot ) :
1337 XclImpRectObj( rRoot ),
1338 mnPolyFlags( 0 ),
1339 mnPointCount( 0 )
1341 SetAreaObj( false ); // polygon may be 2-dimensional
1344 void XclImpPolygonObj::ReadCoordList( XclImpStream& rStrm )
1346 if( (rStrm.GetNextRecId() == EXC_ID_COORDLIST) && rStrm.StartNextRecord() )
1348 OSL_ENSURE( rStrm.GetRecLeft() / 4 == mnPointCount, "XclImpPolygonObj::ReadCoordList - wrong polygon point count" );
1349 while( rStrm.GetRecLeft() >= 4 )
1351 sal_uInt16 nX, nY;
1352 nX = rStrm.ReaduInt16();
1353 nY = rStrm.ReaduInt16();
1354 maCoords.emplace_back( nX, nY );
1359 void XclImpPolygonObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1361 ReadFrameData( rStrm );
1362 mnPolyFlags = rStrm.ReaduInt16();
1363 rStrm.Ignore( 10 );
1364 mnPointCount = rStrm.ReaduInt16();
1365 rStrm.Ignore( 8 );
1366 ReadMacro4( rStrm, nMacroSize );
1367 ReadCoordList( rStrm );
1370 void XclImpPolygonObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1372 ReadFrameData( rStrm );
1373 mnPolyFlags = rStrm.ReaduInt16();
1374 rStrm.Ignore( 10 );
1375 mnPointCount = rStrm.ReaduInt16();
1376 rStrm.Ignore( 8 );
1377 ReadName5( rStrm, nNameLen );
1378 ReadMacro5( rStrm, nMacroSize );
1379 ReadCoordList( rStrm );
1382 namespace {
1384 ::basegfx::B2DPoint lclGetPolyPoint( const tools::Rectangle& rAnchorRect, const Point& rPoint )
1386 return ::basegfx::B2DPoint(
1387 rAnchorRect.Left() + static_cast< sal_Int32 >( ::std::min< double >( rPoint.X(), 16384.0 ) / 16384.0 * rAnchorRect.GetWidth() + 0.5 ),
1388 rAnchorRect.Top() + static_cast< sal_Int32 >( ::std::min< double >( rPoint.Y(), 16384.0 ) / 16384.0 * rAnchorRect.GetHeight() + 0.5 ) );
1391 } // namespace
1393 SdrObjectUniquePtr XclImpPolygonObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1395 SdrObjectUniquePtr xSdrObj;
1396 if( maCoords.size() >= 2 )
1398 // create the polygon
1399 ::basegfx::B2DPolygon aB2DPolygon;
1400 for( const auto& rCoord : maCoords )
1401 aB2DPolygon.append( lclGetPolyPoint( rAnchorRect, rCoord ) );
1402 // close polygon if specified
1403 if( ::get_flag( mnPolyFlags, EXC_OBJ_POLY_CLOSED ) && (maCoords.front() != maCoords.back()) )
1404 aB2DPolygon.append( lclGetPolyPoint( rAnchorRect, maCoords.front() ) );
1405 // create the SdrObject
1406 SdrObjKind eObjKind = maFillData.IsFilled() ? OBJ_PATHPOLY : OBJ_PATHPLIN;
1407 xSdrObj.reset(
1408 new SdrPathObj(
1409 *GetDoc().GetDrawLayer(),
1410 eObjKind,
1411 ::basegfx::B2DPolyPolygon(aB2DPolygon)));
1412 ConvertRectStyle( *xSdrObj );
1414 rDffConv.Progress();
1415 return xSdrObj;
1418 void XclImpObjTextData::ReadByteString( XclImpStream& rStrm )
1420 mxString.reset();
1421 if( maData.mnTextLen > 0 )
1423 mxString.reset( new XclImpString( rStrm.ReadRawByteString( maData.mnTextLen ) ) );
1424 // skip padding byte for word boundaries
1425 if( rStrm.GetRecPos() & 1 ) rStrm.Ignore( 1 );
1429 void XclImpObjTextData::ReadFormats( XclImpStream& rStrm )
1431 if( mxString )
1432 mxString->ReadObjFormats( rStrm, maData.mnFormatSize );
1433 else
1434 rStrm.Ignore( maData.mnFormatSize );
1437 XclImpTextObj::XclImpTextObj( const XclImpRoot& rRoot ) :
1438 XclImpRectObj( rRoot )
1442 void XclImpTextObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1444 ReadFrameData( rStrm );
1445 maTextData.maData.ReadObj3( rStrm );
1446 ReadMacro3( rStrm, nMacroSize );
1447 maTextData.ReadByteString( rStrm );
1448 maTextData.ReadFormats( rStrm );
1451 void XclImpTextObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1453 ReadFrameData( rStrm );
1454 maTextData.maData.ReadObj3( rStrm );
1455 ReadMacro4( rStrm, nMacroSize );
1456 maTextData.ReadByteString( rStrm );
1457 maTextData.ReadFormats( rStrm );
1460 void XclImpTextObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1462 ReadFrameData( rStrm );
1463 maTextData.maData.ReadObj5( rStrm );
1464 ReadName5( rStrm, nNameLen );
1465 ReadMacro5( rStrm, nMacroSize );
1466 maTextData.ReadByteString( rStrm );
1467 rStrm.Ignore( maTextData.maData.mnLinkSize ); // ignore text link formula
1468 maTextData.ReadFormats( rStrm );
1471 SdrObjectUniquePtr XclImpTextObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1473 std::unique_ptr<SdrObjCustomShape, SdrObjectFreeOp> xSdrObj(
1474 new SdrObjCustomShape(
1475 *GetDoc().GetDrawLayer()));
1476 xSdrObj->NbcSetSnapRect( rAnchorRect );
1477 OUString aRectType = "rectangle";
1478 xSdrObj->MergeDefaultAttributes( &aRectType );
1479 ConvertRectStyle( *xSdrObj );
1480 bool bAutoSize = ::get_flag( maTextData.maData.mnFlags, EXC_OBJ_TEXT_AUTOSIZE );
1481 xSdrObj->SetMergedItem( makeSdrTextAutoGrowWidthItem( bAutoSize ) );
1482 xSdrObj->SetMergedItem( makeSdrTextAutoGrowHeightItem( bAutoSize ) );
1483 xSdrObj->SetMergedItem( makeSdrTextWordWrapItem( true ) );
1484 rDffConv.Progress();
1485 return xSdrObj;
1488 void XclImpTextObj::DoPreProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const
1490 // set text data
1491 if( SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( &rSdrObj ) )
1493 if( maTextData.mxString )
1495 if( maTextData.mxString->IsRich() )
1497 // rich text
1498 std::unique_ptr< EditTextObject > xEditObj(
1499 XclImpStringHelper::CreateTextObject( GetRoot(), *maTextData.mxString ) );
1500 std::unique_ptr<OutlinerParaObject> pOutlineObj(new OutlinerParaObject( *xEditObj ));
1501 pOutlineObj->SetOutlinerMode( OutlinerMode::TextObject );
1502 pTextObj->NbcSetOutlinerParaObject( std::move(pOutlineObj) );
1504 else
1506 // plain text
1507 pTextObj->NbcSetText( maTextData.mxString->GetText() );
1510 /* #i96858# Do not apply any formatting if there is no text.
1511 SdrObjCustomShape::SetVerticalWriting (initiated from
1512 SetMergedItem) calls SdrTextObj::ForceOutlinerParaObject which
1513 ensures that we can erroneously write a ClientTextbox record
1514 (with no content) while exporting to XLS, which can cause a
1515 corrupted exported document. */
1517 SvxAdjust eHorAlign = SvxAdjust::Left;
1518 SdrTextVertAdjust eVerAlign = SDRTEXTVERTADJUST_TOP;
1520 // orientation (this is only a fake, drawing does not support real text orientation)
1521 namespace csst = ::com::sun::star::text;
1522 csst::WritingMode eWriteMode = csst::WritingMode_LR_TB;
1523 switch( maTextData.maData.mnOrient )
1525 default:
1526 case EXC_OBJ_ORIENT_NONE:
1528 eWriteMode = csst::WritingMode_LR_TB;
1529 switch( maTextData.maData.GetHorAlign() )
1531 case EXC_OBJ_HOR_LEFT: eHorAlign = SvxAdjust::Left; break;
1532 case EXC_OBJ_HOR_CENTER: eHorAlign = SvxAdjust::Center; break;
1533 case EXC_OBJ_HOR_RIGHT: eHorAlign = SvxAdjust::Right; break;
1534 case EXC_OBJ_HOR_JUSTIFY: eHorAlign = SvxAdjust::Block; break;
1536 switch( maTextData.maData.GetVerAlign() )
1538 case EXC_OBJ_VER_TOP: eVerAlign = SDRTEXTVERTADJUST_TOP; break;
1539 case EXC_OBJ_VER_CENTER: eVerAlign = SDRTEXTVERTADJUST_CENTER; break;
1540 case EXC_OBJ_VER_BOTTOM: eVerAlign = SDRTEXTVERTADJUST_BOTTOM; break;
1541 case EXC_OBJ_VER_JUSTIFY: eVerAlign = SDRTEXTVERTADJUST_BLOCK; break;
1544 break;
1546 case EXC_OBJ_ORIENT_90CCW:
1548 if( SdrObjCustomShape* pObjCustomShape = dynamic_cast< SdrObjCustomShape* >( &rSdrObj ) )
1550 css::beans::PropertyValue aTextRotateAngle;
1551 aTextRotateAngle.Name = "TextRotateAngle";
1552 aTextRotateAngle.Value <<= 180.0;
1553 SdrCustomShapeGeometryItem aGeometryItem(pObjCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ));
1554 aGeometryItem.SetPropertyValue( aTextRotateAngle );
1555 pObjCustomShape->SetMergedItem( aGeometryItem );
1557 eWriteMode = csst::WritingMode_TB_RL;
1558 switch( maTextData.maData.GetHorAlign() )
1560 case EXC_OBJ_HOR_LEFT: eVerAlign = SDRTEXTVERTADJUST_TOP; break;
1561 case EXC_OBJ_HOR_CENTER: eVerAlign = SDRTEXTVERTADJUST_CENTER; break;
1562 case EXC_OBJ_HOR_RIGHT: eVerAlign = SDRTEXTVERTADJUST_BOTTOM; break;
1563 case EXC_OBJ_HOR_JUSTIFY: eVerAlign = SDRTEXTVERTADJUST_BLOCK; break;
1565 MSO_Anchor eTextAnchor = static_cast<MSO_Anchor>(rDffConv.GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop ));
1566 switch( eTextAnchor )
1568 case mso_anchorTopCentered :
1569 case mso_anchorMiddleCentered :
1570 case mso_anchorBottomCentered :
1572 eHorAlign = SvxAdjust::Center;
1574 break;
1576 default:
1578 switch( maTextData.maData.GetVerAlign() )
1580 case EXC_OBJ_VER_TOP: eHorAlign = SvxAdjust::Right; break;
1581 case EXC_OBJ_VER_CENTER: eHorAlign = SvxAdjust::Center; break;
1582 case EXC_OBJ_VER_BOTTOM: eHorAlign = SvxAdjust::Left; break;
1583 case EXC_OBJ_VER_JUSTIFY: eHorAlign = SvxAdjust::Block; break;
1588 break;
1590 case EXC_OBJ_ORIENT_STACKED:
1592 // sj: STACKED is not supported, maybe it can be optimized here a bit
1593 [[fallthrough]];
1595 case EXC_OBJ_ORIENT_90CW:
1597 eWriteMode = csst::WritingMode_TB_RL;
1598 switch( maTextData.maData.GetHorAlign() )
1600 case EXC_OBJ_HOR_LEFT: eVerAlign = SDRTEXTVERTADJUST_BOTTOM; break;
1601 case EXC_OBJ_HOR_CENTER: eVerAlign = SDRTEXTVERTADJUST_CENTER; break;
1602 case EXC_OBJ_HOR_RIGHT: eVerAlign = SDRTEXTVERTADJUST_TOP; break;
1603 case EXC_OBJ_HOR_JUSTIFY: eVerAlign = SDRTEXTVERTADJUST_BLOCK; break;
1605 MSO_Anchor eTextAnchor = static_cast<MSO_Anchor>(rDffConv.GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop ));
1606 switch ( eTextAnchor )
1608 case mso_anchorTopCentered :
1609 case mso_anchorMiddleCentered :
1610 case mso_anchorBottomCentered :
1612 eHorAlign = SvxAdjust::Center;
1614 break;
1616 default:
1618 switch( maTextData.maData.GetVerAlign() )
1620 case EXC_OBJ_VER_TOP: eHorAlign = SvxAdjust::Left; break;
1621 case EXC_OBJ_VER_CENTER: eHorAlign = SvxAdjust::Center; break;
1622 case EXC_OBJ_VER_BOTTOM: eHorAlign = SvxAdjust::Right; break;
1623 case EXC_OBJ_VER_JUSTIFY: eHorAlign = SvxAdjust::Block; break;
1628 break;
1630 rSdrObj.SetMergedItem( SvxAdjustItem( eHorAlign, EE_PARA_JUST ) );
1631 rSdrObj.SetMergedItem( SdrTextVertAdjustItem( eVerAlign ) );
1632 rSdrObj.SetMergedItem( SvxWritingModeItem( eWriteMode, SDRATTR_TEXTDIRECTION ) );
1635 // base class processing
1636 XclImpRectObj::DoPreProcessSdrObj( rDffConv, rSdrObj );
1639 XclImpChartObj::XclImpChartObj( const XclImpRoot& rRoot, bool bOwnTab ) :
1640 XclImpRectObj( rRoot ),
1641 mbOwnTab( bOwnTab )
1643 SetSimpleMacro( false );
1644 SetCustomDffObj( true );
1647 void XclImpChartObj::ReadChartSubStream( XclImpStream& rStrm )
1649 /* If chart is read from a chartsheet (mbOwnTab == true), the BOF record
1650 has already been read. If chart is embedded as object, the next record
1651 has to be the BOF record. */
1652 if( mbOwnTab )
1654 /* #i109800# The input stream may point somewhere inside the chart
1655 substream and not exactly to the leading BOF record. To read this
1656 record correctly in the following, the stream has to rewind it, so
1657 that the next call to StartNextRecord() will find it correctly. */
1658 if( rStrm.GetRecId() != EXC_ID5_BOF )
1659 rStrm.RewindRecord();
1661 else
1663 if( (rStrm.GetNextRecId() == EXC_ID5_BOF) && rStrm.StartNextRecord() )
1665 sal_uInt16 nBofType;
1666 rStrm.Seek( 2 );
1667 nBofType = rStrm.ReaduInt16();
1668 SAL_WARN_IF( nBofType != EXC_BOF_CHART, "sc.filter", "XclImpChartObj::ReadChartSubStream - no chart BOF record" );
1670 else
1672 SAL_INFO("sc.filter", "XclImpChartObj::ReadChartSubStream - missing chart substream");
1673 return;
1677 // read chart, even if BOF record contains wrong substream identifier
1678 mxChart.reset( new XclImpChart( GetRoot(), mbOwnTab ) );
1679 mxChart->ReadChartSubStream( rStrm );
1680 if( mbOwnTab )
1681 FinalizeTabChart();
1684 void XclImpChartObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1686 // read OBJ record and the following chart substream
1687 ReadFrameData( rStrm );
1688 rStrm.Ignore( 18 );
1689 ReadMacro3( rStrm, nMacroSize );
1690 // set frame format from OBJ record, it is used if chart itself is transparent
1691 if( mxChart )
1692 mxChart->UpdateObjFrame( maLineData, maFillData );
1695 void XclImpChartObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1697 // read OBJ record and the following chart substream
1698 ReadFrameData( rStrm );
1699 rStrm.Ignore( 18 );
1700 ReadMacro4( rStrm, nMacroSize );
1701 // set frame format from OBJ record, it is used if chart itself is transparent
1702 if( mxChart )
1703 mxChart->UpdateObjFrame( maLineData, maFillData );
1706 void XclImpChartObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1708 // read OBJ record and the following chart substream
1709 ReadFrameData( rStrm );
1710 rStrm.Ignore( 18 );
1711 ReadName5( rStrm, nNameLen );
1712 ReadMacro5( rStrm, nMacroSize );
1713 ReadChartSubStream( rStrm );
1714 // set frame format from OBJ record, it is used if chart itself is transparent
1715 if( mxChart )
1716 mxChart->UpdateObjFrame( maLineData, maFillData );
1719 void XclImpChartObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 /*nSubRecSize*/ )
1721 // read the following chart substream
1722 if( nSubRecId == EXC_ID_OBJEND )
1724 // enable CONTINUE handling for the entire chart substream
1725 rStrm.ResetRecord( true );
1726 ReadChartSubStream( rStrm );
1727 /* disable CONTINUE handling again to be able to read
1728 following CONTINUE records as MSODRAWING records. */
1729 rStrm.ResetRecord( false );
1733 std::size_t XclImpChartObj::DoGetProgressSize() const
1735 return mxChart ? mxChart->GetProgressSize() : 1;
1738 SdrObjectUniquePtr XclImpChartObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1740 SdrObjectUniquePtr xSdrObj;
1741 SfxObjectShell* pDocShell = GetDocShell();
1742 if( rDffConv.SupportsOleObjects() && SvtModuleOptions().IsChart() && pDocShell && mxChart && !mxChart->IsPivotChart() )
1744 // create embedded chart object
1745 OUString aEmbObjName;
1746 OUString sBaseURL(GetRoot().GetMedium().GetBaseURL());
1747 Reference< XEmbeddedObject > xEmbObj = pDocShell->GetEmbeddedObjectContainer().
1748 CreateEmbeddedObject( SvGlobalName( SO3_SCH_CLASSID ).GetByteSequence(), aEmbObjName, &sBaseURL );
1750 /* Set the size to the embedded object, this prevents that font sizes
1751 of text objects are changed in the chart when the object is
1752 inserted into the draw page. */
1753 sal_Int64 nAspect = css::embed::Aspects::MSOLE_CONTENT;
1754 MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xEmbObj->getMapUnit( nAspect ) );
1755 Size aSize( vcl::Window::LogicToLogic( rAnchorRect.GetSize(), MapMode( MapUnit::Map100thMM ), MapMode( aUnit ) ) );
1756 css::awt::Size aAwtSize( aSize.Width(), aSize.Height() );
1757 xEmbObj->setVisualAreaSize( nAspect, aAwtSize );
1759 // #i121334# This call will change the chart's default background fill from white to transparent.
1760 // Add here again if this is wanted (see task description for details)
1761 // ChartHelper::AdaptDefaultsForChart( xEmbObj );
1763 // create the container OLE object
1764 xSdrObj.reset(
1765 new SdrOle2Obj(
1766 *GetDoc().GetDrawLayer(),
1767 svt::EmbeddedObjectRef(xEmbObj, nAspect),
1768 aEmbObjName,
1769 rAnchorRect));
1772 return xSdrObj;
1775 void XclImpChartObj::DoPostProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const
1777 const SdrOle2Obj* pSdrOleObj = dynamic_cast< const SdrOle2Obj* >( &rSdrObj );
1778 if( mxChart && pSdrOleObj )
1780 const Reference< XEmbeddedObject >& xEmbObj = pSdrOleObj->GetObjRef();
1781 if( xEmbObj.is() && ::svt::EmbeddedObjectRef::TryRunningState( xEmbObj ) ) try
1783 Reference< XEmbedPersist > xPersist( xEmbObj, UNO_QUERY_THROW );
1784 Reference< XModel > xModel( xEmbObj->getComponent(), UNO_QUERY_THROW );
1785 mxChart->Convert( xModel, rDffConv, xPersist->getEntryName(), rSdrObj.GetLogicRect() );
1787 catch( const Exception& )
1793 void XclImpChartObj::FinalizeTabChart()
1795 /* #i44077# Calculate and store DFF anchor for sheet charts.
1796 Needed to get used area if this chart is inserted as OLE object. */
1797 OSL_ENSURE( mbOwnTab, "XclImpChartObj::FinalizeTabChart - not allowed for embedded chart objects" );
1799 // set uninitialized page to landscape
1800 if( !GetPageSettings().GetPageData().mbValid )
1801 GetPageSettings().SetPaperSize( EXC_PAPERSIZE_DEFAULT, false );
1803 // calculate size of the chart object
1804 const XclPageData& rPageData = GetPageSettings().GetPageData();
1805 Size aPaperSize = rPageData.GetScPaperSize();
1807 long nWidth = XclTools::GetHmmFromTwips( aPaperSize.Width() );
1808 long nHeight = XclTools::GetHmmFromTwips( aPaperSize.Height() );
1810 // subtract page margins, give some more extra space
1811 nWidth -= (XclTools::GetHmmFromInch( rPageData.mfLeftMargin + rPageData.mfRightMargin ) + 2000);
1812 nHeight -= (XclTools::GetHmmFromInch( rPageData.mfTopMargin + rPageData.mfBottomMargin ) + 1000);
1814 // print column/row headers?
1815 if( rPageData.mbPrintHeadings )
1817 nWidth -= 2000;
1818 nHeight -= 1000;
1821 // create the object anchor
1822 XclObjAnchor aAnchor;
1823 aAnchor.SetRect( GetRoot(), GetCurrScTab(), tools::Rectangle( 1000, 500, nWidth, nHeight ), MapUnit::Map100thMM );
1824 SetAnchor( aAnchor );
1827 XclImpNoteObj::XclImpNoteObj( const XclImpRoot& rRoot ) :
1828 XclImpTextObj( rRoot ),
1829 maScPos( ScAddress::INITIALIZE_INVALID ),
1830 mnNoteFlags( 0 )
1832 SetSimpleMacro( false );
1833 // caption object will be created manually
1834 SetInsertSdrObj( false );
1837 void XclImpNoteObj::SetNoteData( const ScAddress& rScPos, sal_uInt16 nNoteFlags )
1839 maScPos = rScPos;
1840 mnNoteFlags = nNoteFlags;
1843 void XclImpNoteObj::DoPreProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const
1845 // create formatted text
1846 XclImpTextObj::DoPreProcessSdrObj( rDffConv, rSdrObj );
1847 OutlinerParaObject* pOutlinerObj = rSdrObj.GetOutlinerParaObject();
1848 if( maScPos.IsValid() && pOutlinerObj )
1850 // create cell note with all data from drawing object
1851 ScNoteUtil::CreateNoteFromObjectData(
1852 GetDoc(), maScPos,
1853 rSdrObj.GetMergedItemSet().Clone(), // new object on heap expected
1854 new OutlinerParaObject( *pOutlinerObj ), // new object on heap expected
1855 rSdrObj.GetLogicRect(),
1856 ::get_flag( mnNoteFlags, EXC_NOTE_VISIBLE ) );
1860 XclImpControlHelper::XclImpControlHelper( const XclImpRoot& rRoot, XclCtrlBindMode eBindMode ) :
1861 mrRoot( rRoot ),
1862 meBindMode( eBindMode )
1866 XclImpControlHelper::~XclImpControlHelper()
1870 SdrObjectUniquePtr XclImpControlHelper::CreateSdrObjectFromShape(
1871 const Reference< XShape >& rxShape, const tools::Rectangle& rAnchorRect ) const
1873 mxShape = rxShape;
1874 SdrObjectUniquePtr xSdrObj( SdrObject::getSdrObjectFromXShape( rxShape ) );
1875 if( xSdrObj )
1877 xSdrObj->NbcSetSnapRect( rAnchorRect );
1878 // #i30543# insert into control layer
1879 xSdrObj->NbcSetLayer( SC_LAYER_CONTROLS );
1881 return xSdrObj;
1884 void XclImpControlHelper::ApplySheetLinkProps() const
1887 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( mxShape );
1888 if( !xCtrlModel.is() )
1889 return;
1890 ScfPropertySet aPropSet( xCtrlModel );
1892 // sheet links
1893 if( SfxObjectShell* pDocShell = mrRoot.GetDocShell() )
1895 Reference< XMultiServiceFactory > xFactory( pDocShell->GetModel(), UNO_QUERY );
1896 if( xFactory.is() )
1898 // cell link
1899 if( mxCellLink ) try
1901 Reference< XBindableValue > xBindable( xCtrlModel, UNO_QUERY_THROW );
1903 // create argument sequence for createInstanceWithArguments()
1904 CellAddress aApiAddress;
1905 ScUnoConversion::FillApiAddress( aApiAddress, *mxCellLink );
1907 NamedValue aValue;
1908 aValue.Name = SC_UNONAME_BOUNDCELL;
1909 aValue.Value <<= aApiAddress;
1911 Sequence< Any > aArgs( 1 );
1912 aArgs[ 0 ] <<= aValue;
1914 // create the CellValueBinding instance and set at the control model
1915 OUString aServiceName;
1916 switch( meBindMode )
1918 case EXC_CTRL_BINDCONTENT: aServiceName = SC_SERVICENAME_VALBIND; break;
1919 case EXC_CTRL_BINDPOSITION: aServiceName = SC_SERVICENAME_LISTCELLBIND; break;
1921 Reference< XValueBinding > xBinding(
1922 xFactory->createInstanceWithArguments( aServiceName, aArgs ), UNO_QUERY_THROW );
1923 xBindable->setValueBinding( xBinding );
1925 catch( const Exception& )
1929 // source range
1930 if( mxSrcRange ) try
1932 Reference< XListEntrySink > xEntrySink( xCtrlModel, UNO_QUERY_THROW );
1934 // create argument sequence for createInstanceWithArguments()
1935 CellRangeAddress aApiRange;
1936 ScUnoConversion::FillApiRange( aApiRange, *mxSrcRange );
1938 NamedValue aValue;
1939 aValue.Name = SC_UNONAME_CELLRANGE;
1940 aValue.Value <<= aApiRange;
1942 Sequence< Any > aArgs( 1 );
1943 aArgs[ 0 ] <<= aValue;
1945 // create the EntrySource instance and set at the control model
1946 Reference< XListEntrySource > xEntrySource( xFactory->createInstanceWithArguments(
1947 SC_SERVICENAME_LISTSOURCE, aArgs ), UNO_QUERY_THROW );
1948 xEntrySink->setListEntrySource( xEntrySource );
1950 catch( const Exception& )
1957 void XclImpControlHelper::ProcessControl( const XclImpDrawObjBase& rDrawObj ) const
1959 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( mxShape );
1960 if( !xCtrlModel.is() )
1961 return;
1963 ApplySheetLinkProps();
1965 ScfPropertySet aPropSet( xCtrlModel );
1967 // #i51348# set object name at control model
1968 aPropSet.SetStringProperty( "Name", rDrawObj.GetObjName() );
1970 // control visible and printable?
1971 aPropSet.SetBoolProperty( "EnableVisible", rDrawObj.IsVisible() );
1972 aPropSet.SetBoolProperty( "Printable", rDrawObj.IsPrintable() );
1974 // virtual call for type specific processing
1975 DoProcessControl( aPropSet );
1978 void XclImpControlHelper::ReadCellLinkFormula( XclImpStream& rStrm, bool bWithBoundSize )
1980 ScRangeList aScRanges;
1981 ReadRangeList( aScRanges, rStrm, bWithBoundSize );
1982 // Use first cell of first range
1983 if ( !aScRanges.empty() )
1985 const ScRange & rScRange = aScRanges.front();
1986 mxCellLink.reset( new ScAddress( rScRange.aStart ) );
1990 void XclImpControlHelper::ReadSourceRangeFormula( XclImpStream& rStrm, bool bWithBoundSize )
1992 ScRangeList aScRanges;
1993 ReadRangeList( aScRanges, rStrm, bWithBoundSize );
1994 // Use first range
1995 if ( !aScRanges.empty() )
1997 const ScRange & rScRange = aScRanges.front();
1998 mxSrcRange.reset( new ScRange( rScRange ) );
2002 void XclImpControlHelper::DoProcessControl( ScfPropertySet& ) const
2006 void XclImpControlHelper::ReadRangeList( ScRangeList& rScRanges, XclImpStream& rStrm )
2008 XclTokenArray aXclTokArr;
2009 aXclTokArr.ReadSize( rStrm );
2010 rStrm.Ignore( 4 );
2011 aXclTokArr.ReadArray( rStrm );
2012 mrRoot.GetFormulaCompiler().CreateRangeList( rScRanges, EXC_FMLATYPE_CONTROL, aXclTokArr, rStrm );
2015 void XclImpControlHelper::ReadRangeList( ScRangeList& rScRanges, XclImpStream& rStrm, bool bWithBoundSize )
2017 if( bWithBoundSize )
2019 sal_uInt16 nSize;
2020 nSize = rStrm.ReaduInt16();
2021 if( nSize > 0 )
2023 rStrm.PushPosition();
2024 ReadRangeList( rScRanges, rStrm );
2025 rStrm.PopPosition();
2026 rStrm.Ignore( nSize );
2029 else
2031 ReadRangeList( rScRanges, rStrm );
2035 XclImpTbxObjBase::XclImpTbxObjBase( const XclImpRoot& rRoot ) :
2036 XclImpTextObj( rRoot ),
2037 XclImpControlHelper( rRoot, EXC_CTRL_BINDPOSITION )
2039 SetSimpleMacro( false );
2040 SetCustomDffObj( true );
2043 namespace {
2045 void lclExtractColor( sal_uInt8& rnColorIdx, const DffPropSet& rDffPropSet, sal_uInt32 nPropId )
2047 if( rDffPropSet.IsProperty( nPropId ) )
2049 sal_uInt32 nColor = rDffPropSet.GetPropertyValue( nPropId, 0 );
2050 if( (nColor & 0xFF000000) == 0x08000000 )
2051 rnColorIdx = ::extract_value< sal_uInt8 >( nColor, 0, 8 );
2055 } // namespace
2057 void XclImpTbxObjBase::SetDffProperties( const DffPropSet& rDffPropSet )
2059 maFillData.mnPattern = rDffPropSet.GetPropertyBool( DFF_Prop_fFilled ) ? EXC_PATT_SOLID : EXC_PATT_NONE;
2060 lclExtractColor( maFillData.mnBackColorIdx, rDffPropSet, DFF_Prop_fillBackColor );
2061 lclExtractColor( maFillData.mnPattColorIdx, rDffPropSet, DFF_Prop_fillColor );
2062 ::set_flag( maFillData.mnAuto, EXC_OBJ_LINE_AUTO, false );
2064 maLineData.mnStyle = rDffPropSet.GetPropertyBool( DFF_Prop_fLine ) ? EXC_OBJ_LINE_SOLID : EXC_OBJ_LINE_NONE;
2065 lclExtractColor( maLineData.mnColorIdx, rDffPropSet, DFF_Prop_lineColor );
2066 ::set_flag( maLineData.mnAuto, EXC_OBJ_FILL_AUTO, false );
2069 bool XclImpTbxObjBase::FillMacroDescriptor( ScriptEventDescriptor& rDescriptor ) const
2071 return XclControlHelper::FillMacroDescriptor( rDescriptor, DoGetEventType(), GetMacroName(), GetDocShell() );
2074 void XclImpTbxObjBase::ConvertFont( ScfPropertySet& rPropSet ) const
2076 if( maTextData.mxString )
2078 const XclFormatRunVec& rFormatRuns = maTextData.mxString->GetFormats();
2079 if( rFormatRuns.empty() )
2080 GetFontBuffer().WriteDefaultCtrlFontProperties( rPropSet );
2081 else
2082 GetFontBuffer().WriteFontProperties( rPropSet, EXC_FONTPROPSET_CONTROL, rFormatRuns.front().mnFontIdx );
2086 void XclImpTbxObjBase::ConvertLabel( ScfPropertySet& rPropSet ) const
2088 if( maTextData.mxString )
2090 OUString aLabel = maTextData.mxString->GetText();
2091 if( maTextData.maData.mnShortcut > 0 )
2093 sal_Int32 nPos = aLabel.indexOf( static_cast< sal_Unicode >( maTextData.maData.mnShortcut ) );
2094 if( nPos != -1 )
2095 aLabel = aLabel.replaceAt( nPos, 0, "~" );
2097 rPropSet.SetStringProperty( "Label", aLabel );
2099 //Excel Alt text <==> Aoo description
2100 //For TBX control, if user does not operate alt text, alt text will be set label text as default value in Excel.
2101 //In this case, DFF_Prop_wzDescription will not be set in excel file.
2102 //So In the end of SvxMSDffManager::ImportShape, description will not be set. But actually in excel,
2103 //the alt text is the label value. So here set description as label text first which is called before ImportShape.
2104 Reference< css::beans::XPropertySet > xPropset( mxShape, UNO_QUERY );
2105 try{
2106 if(xPropset.is())
2107 xPropset->setPropertyValue( "Description", makeAny(aLabel) );
2108 }catch( ... )
2110 SAL_WARN("sc.filter", "Can't set a default text for TBX Control ");
2113 ConvertFont( rPropSet );
2116 SdrObjectUniquePtr XclImpTbxObjBase::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
2118 SdrObjectUniquePtr xSdrObj( rDffConv.CreateSdrObject( *this, rAnchorRect ) );
2119 rDffConv.Progress();
2120 return xSdrObj;
2123 void XclImpTbxObjBase::DoPreProcessSdrObj( XclImpDffConverter& /*rDffConv*/, SdrObject& /*rSdrObj*/ ) const
2125 // do not call DoPreProcessSdrObj() from base class (to skip text processing)
2126 ProcessControl( *this );
2129 XclImpButtonObj::XclImpButtonObj( const XclImpRoot& rRoot ) :
2130 XclImpTbxObjBase( rRoot )
2134 void XclImpButtonObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2136 // label and text formatting
2137 ConvertLabel( rPropSet );
2139 /* Horizontal text alignment. For unknown reason, the property type is a
2140 simple sal_Int16 and not a com.sun.star.style.HorizontalAlignment. */
2141 sal_Int16 nHorAlign = 1;
2142 switch( maTextData.maData.GetHorAlign() )
2144 case EXC_OBJ_HOR_LEFT: nHorAlign = 0; break;
2145 case EXC_OBJ_HOR_CENTER: nHorAlign = 1; break;
2146 case EXC_OBJ_HOR_RIGHT: nHorAlign = 2; break;
2148 rPropSet.SetProperty( "Align", nHorAlign );
2150 // vertical text alignment
2151 namespace csss = ::com::sun::star::style;
2152 csss::VerticalAlignment eVerAlign = csss::VerticalAlignment_MIDDLE;
2153 switch( maTextData.maData.GetVerAlign() )
2155 case EXC_OBJ_VER_TOP: eVerAlign = csss::VerticalAlignment_TOP; break;
2156 case EXC_OBJ_VER_CENTER: eVerAlign = csss::VerticalAlignment_MIDDLE; break;
2157 case EXC_OBJ_VER_BOTTOM: eVerAlign = csss::VerticalAlignment_BOTTOM; break;
2159 rPropSet.SetProperty( "VerticalAlign", eVerAlign );
2161 // always wrap text automatically
2162 rPropSet.SetBoolProperty( "MultiLine", true );
2164 // default button
2165 bool bDefButton = ::get_flag( maTextData.maData.mnButtonFlags, EXC_OBJ_BUTTON_DEFAULT );
2166 rPropSet.SetBoolProperty( "DefaultButton", bDefButton );
2168 // button type (flags cannot be combined in OOo)
2169 namespace cssa = ::com::sun::star::awt;
2170 cssa::PushButtonType eButtonType = cssa::PushButtonType_STANDARD;
2171 if( ::get_flag( maTextData.maData.mnButtonFlags, EXC_OBJ_BUTTON_CLOSE ) )
2172 eButtonType = cssa::PushButtonType_OK;
2173 else if( ::get_flag( maTextData.maData.mnButtonFlags, EXC_OBJ_BUTTON_CANCEL ) )
2174 eButtonType = cssa::PushButtonType_CANCEL;
2175 else if( ::get_flag( maTextData.maData.mnButtonFlags, EXC_OBJ_BUTTON_HELP ) )
2176 eButtonType = cssa::PushButtonType_HELP;
2177 // property type is short, not enum
2178 rPropSet.SetProperty( "PushButtonType", sal_Int16( eButtonType ) );
2181 OUString XclImpButtonObj::DoGetServiceName() const
2183 return "com.sun.star.form.component.CommandButton";
2186 XclTbxEventType XclImpButtonObj::DoGetEventType() const
2188 return EXC_TBX_EVENT_ACTION;
2191 XclImpCheckBoxObj::XclImpCheckBoxObj( const XclImpRoot& rRoot ) :
2192 XclImpTbxObjBase( rRoot ),
2193 mnState( EXC_OBJ_CHECKBOX_UNCHECKED ),
2194 mnCheckBoxFlags( 0 )
2198 void XclImpCheckBoxObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2200 ReadFrameData( rStrm );
2201 rStrm.Ignore( 10 );
2202 maTextData.maData.mnFlags = rStrm.ReaduInt16();
2203 rStrm.Ignore( 20 );
2204 ReadName5( rStrm, nNameLen );
2205 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2206 ReadCellLinkFormula( rStrm, true );
2207 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2208 maTextData.ReadByteString( rStrm );
2209 mnState = rStrm.ReaduInt16();
2210 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2211 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16();
2212 mnCheckBoxFlags = rStrm.ReaduInt16();
2215 void XclImpCheckBoxObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2217 switch( nSubRecId )
2219 case EXC_ID_OBJCBLS:
2220 // do not read EXC_ID_OBJCBLSDATA, not written by OOo Excel export
2221 mnState = rStrm.ReaduInt16();
2222 rStrm.Ignore( 4 );
2223 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2224 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16();
2225 mnCheckBoxFlags = rStrm.ReaduInt16();
2226 break;
2227 case EXC_ID_OBJCBLSFMLA:
2228 ReadCellLinkFormula( rStrm, false );
2229 break;
2230 default:
2231 XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2235 void XclImpCheckBoxObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2237 // label and text formatting
2238 ConvertLabel( rPropSet );
2240 // state
2241 bool bSupportsTristate = GetObjType() == EXC_OBJTYPE_CHECKBOX;
2242 sal_Int16 nApiState = 0;
2243 switch( mnState )
2245 case EXC_OBJ_CHECKBOX_UNCHECKED: nApiState = 0; break;
2246 case EXC_OBJ_CHECKBOX_CHECKED: nApiState = 1; break;
2247 case EXC_OBJ_CHECKBOX_TRISTATE: nApiState = bSupportsTristate ? 2 : 1; break;
2249 if( bSupportsTristate )
2250 rPropSet.SetBoolProperty( "TriState", nApiState == 2 );
2251 rPropSet.SetProperty( "DefaultState", nApiState );
2253 // box style
2254 namespace AwtVisualEffect = ::com::sun::star::awt::VisualEffect;
2255 sal_Int16 nEffect = ::get_flagvalue( mnCheckBoxFlags, EXC_OBJ_CHECKBOX_FLAT, AwtVisualEffect::FLAT, AwtVisualEffect::LOOK3D );
2256 rPropSet.SetProperty( "VisualEffect", nEffect );
2258 // do not wrap text automatically
2259 rPropSet.SetBoolProperty( "MultiLine", false );
2261 // #i40279# always centered vertically
2262 namespace csss = ::com::sun::star::style;
2263 rPropSet.SetProperty( "VerticalAlign", csss::VerticalAlignment_MIDDLE );
2265 // background color
2266 if( maFillData.IsFilled() )
2268 sal_Int32 nColor = static_cast< sal_Int32 >( GetSolidFillColor( maFillData ) );
2269 rPropSet.SetProperty( "BackgroundColor", nColor );
2273 OUString XclImpCheckBoxObj::DoGetServiceName() const
2275 return "com.sun.star.form.component.CheckBox";
2278 XclTbxEventType XclImpCheckBoxObj::DoGetEventType() const
2280 return EXC_TBX_EVENT_ACTION;
2283 XclImpOptionButtonObj::XclImpOptionButtonObj( const XclImpRoot& rRoot ) :
2284 XclImpCheckBoxObj( rRoot ),
2285 mnNextInGroup( 0 ),
2286 mnFirstInGroup( 1 )
2290 void XclImpOptionButtonObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2292 ReadFrameData( rStrm );
2293 rStrm.Ignore( 10 );
2294 maTextData.maData.mnFlags = rStrm.ReaduInt16();
2295 rStrm.Ignore( 32 );
2296 ReadName5( rStrm, nNameLen );
2297 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2298 ReadCellLinkFormula( rStrm, true );
2299 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2300 maTextData.ReadByteString( rStrm );
2301 mnState = rStrm.ReaduInt16();
2302 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2303 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16();
2304 mnCheckBoxFlags = rStrm.ReaduInt16();
2305 mnNextInGroup = rStrm.ReaduInt16();
2306 mnFirstInGroup = rStrm.ReaduInt16();
2309 void XclImpOptionButtonObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2311 switch( nSubRecId )
2313 case EXC_ID_OBJRBODATA:
2314 mnNextInGroup = rStrm.ReaduInt16();
2315 mnFirstInGroup = rStrm.ReaduInt16();
2316 break;
2317 default:
2318 XclImpCheckBoxObj::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2322 void XclImpOptionButtonObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2324 XclImpCheckBoxObj::DoProcessControl( rPropSet );
2325 // TODO: grouping
2326 XclImpOptionButtonObj* pTbxObj = dynamic_cast< XclImpOptionButtonObj* >( GetObjectManager().GetSheetDrawing( GetTab() ).FindDrawObj( mnNextInGroup ).get() );
2327 if ( pTbxObj && pTbxObj->mnFirstInGroup )
2329 // Group has terminated
2330 // traverse each RadioButton in group and
2331 // a) apply the groupname
2332 // b) propagate the linked cell from the lead radiobutton
2333 // c) apply the correct Ref value
2334 XclImpOptionButtonObj* pLeader = pTbxObj;
2336 sal_Int32 nRefVal = 1;
2340 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( pTbxObj->mxShape );
2341 if ( xCtrlModel.is() )
2343 ScfPropertySet aProps( xCtrlModel );
2344 OUString sGroupName = OUString::number( pLeader->GetDffShapeId() );
2346 aProps.SetStringProperty( "GroupName", sGroupName );
2347 aProps.SetStringProperty( "RefValue", OUString::number( nRefVal++ ) );
2348 if ( pLeader->HasCellLink() && !pTbxObj->HasCellLink() )
2350 // propagate cell link info
2351 pTbxObj->mxCellLink.reset( new ScAddress( *pLeader->mxCellLink ) );
2352 pTbxObj->ApplySheetLinkProps();
2354 pTbxObj = dynamic_cast< XclImpOptionButtonObj* >( GetObjectManager().GetSheetDrawing( GetTab() ).FindDrawObj( pTbxObj->mnNextInGroup ).get() );
2356 else
2357 pTbxObj = nullptr;
2358 } while ( pTbxObj && ( pTbxObj->mnFirstInGroup != 1 ) );
2360 else
2362 // not the leader? try and find it
2366 OUString XclImpOptionButtonObj::DoGetServiceName() const
2368 return "com.sun.star.form.component.RadioButton";
2371 XclTbxEventType XclImpOptionButtonObj::DoGetEventType() const
2373 return EXC_TBX_EVENT_ACTION;
2376 XclImpLabelObj::XclImpLabelObj( const XclImpRoot& rRoot ) :
2377 XclImpTbxObjBase( rRoot )
2381 void XclImpLabelObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2383 // label and text formatting
2384 ConvertLabel( rPropSet );
2386 // text alignment (always top/left aligned)
2387 rPropSet.SetProperty( "Align", sal_Int16( 0 ) );
2388 namespace csss = ::com::sun::star::style;
2389 rPropSet.SetProperty( "VerticalAlign", csss::VerticalAlignment_TOP );
2391 // always wrap text automatically
2392 rPropSet.SetBoolProperty( "MultiLine", true );
2395 OUString XclImpLabelObj::DoGetServiceName() const
2397 return "com.sun.star.form.component.FixedText";
2400 XclTbxEventType XclImpLabelObj::DoGetEventType() const
2402 return EXC_TBX_EVENT_MOUSE;
2405 XclImpGroupBoxObj::XclImpGroupBoxObj( const XclImpRoot& rRoot ) :
2406 XclImpTbxObjBase( rRoot ),
2407 mnGroupBoxFlags( 0 )
2411 void XclImpGroupBoxObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2413 ReadFrameData( rStrm );
2414 rStrm.Ignore( 10 );
2415 maTextData.maData.mnFlags = rStrm.ReaduInt16();
2416 rStrm.Ignore( 26 );
2417 ReadName5( rStrm, nNameLen );
2418 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2419 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2420 maTextData.ReadByteString( rStrm );
2421 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2422 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16( );
2423 mnGroupBoxFlags = rStrm.ReaduInt16();
2426 void XclImpGroupBoxObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2428 switch( nSubRecId )
2430 case EXC_ID_OBJGBODATA:
2431 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2432 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16();
2433 mnGroupBoxFlags = rStrm.ReaduInt16();
2434 break;
2435 default:
2436 XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2440 void XclImpGroupBoxObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2442 // label and text formatting
2443 ConvertLabel( rPropSet );
2446 OUString XclImpGroupBoxObj::DoGetServiceName() const
2448 return "com.sun.star.form.component.GroupBox";
2451 XclTbxEventType XclImpGroupBoxObj::DoGetEventType() const
2453 return EXC_TBX_EVENT_MOUSE;
2456 XclImpDialogObj::XclImpDialogObj( const XclImpRoot& rRoot ) :
2457 XclImpTbxObjBase( rRoot )
2461 void XclImpDialogObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2463 // label and text formatting
2464 ConvertLabel( rPropSet );
2467 OUString XclImpDialogObj::DoGetServiceName() const
2469 // dialog frame faked by a groupbox
2470 return "com.sun.star.form.component.GroupBox";
2473 XclTbxEventType XclImpDialogObj::DoGetEventType() const
2475 return EXC_TBX_EVENT_MOUSE;
2478 XclImpEditObj::XclImpEditObj( const XclImpRoot& rRoot ) :
2479 XclImpTbxObjBase( rRoot ),
2480 mnContentType( EXC_OBJ_EDIT_TEXT ),
2481 mnMultiLine( 0 ),
2482 mnScrollBar( 0 ),
2483 mnListBoxObjId( 0 )
2487 bool XclImpEditObj::IsNumeric() const
2489 return (mnContentType == EXC_OBJ_EDIT_INTEGER) || (mnContentType == EXC_OBJ_EDIT_DOUBLE);
2492 void XclImpEditObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2494 ReadFrameData( rStrm );
2495 rStrm.Ignore( 10 );
2496 maTextData.maData.mnFlags = rStrm.ReaduInt16();
2497 rStrm.Ignore( 14 );
2498 ReadName5( rStrm, nNameLen );
2499 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2500 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2501 maTextData.ReadByteString( rStrm );
2502 mnContentType = rStrm.ReaduInt16();
2503 mnMultiLine = rStrm.ReaduInt16();
2504 mnScrollBar = rStrm.ReaduInt16();
2505 mnListBoxObjId = rStrm.ReaduInt16();
2508 void XclImpEditObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2510 switch( nSubRecId )
2512 case EXC_ID_OBJEDODATA:
2513 mnContentType = rStrm.ReaduInt16();
2514 mnMultiLine = rStrm.ReaduInt16();
2515 mnScrollBar = rStrm.ReaduInt16();
2516 mnListBoxObjId = rStrm.ReaduInt16();
2517 break;
2518 default:
2519 XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2523 void XclImpEditObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2525 if( maTextData.mxString )
2527 OUString aText = maTextData.mxString->GetText();
2528 if( IsNumeric() )
2530 // TODO: OUString::toDouble() does not handle local decimal separator
2531 rPropSet.SetProperty( "DefaultValue", aText.toDouble() );
2532 rPropSet.SetBoolProperty( "Spin", mnScrollBar != 0 );
2534 else
2536 rPropSet.SetProperty( "DefaultText", aText );
2537 rPropSet.SetBoolProperty( "MultiLine", mnMultiLine != 0 );
2538 rPropSet.SetBoolProperty( "VScroll", mnScrollBar != 0 );
2541 ConvertFont( rPropSet );
2544 OUString XclImpEditObj::DoGetServiceName() const
2546 return IsNumeric() ?
2547 OUString( "com.sun.star.form.component.NumericField" ) :
2548 OUString( "com.sun.star.form.component.TextField" );
2551 XclTbxEventType XclImpEditObj::DoGetEventType() const
2553 return EXC_TBX_EVENT_TEXT;
2556 XclImpTbxObjScrollableBase::XclImpTbxObjScrollableBase( const XclImpRoot& rRoot ) :
2557 XclImpTbxObjBase( rRoot ),
2558 mnValue( 0 ),
2559 mnMin( 0 ),
2560 mnMax( 100 ),
2561 mnStep( 1 ),
2562 mnPageStep( 10 ),
2563 mnOrient( 0 ),
2564 mnThumbWidth( 1 ),
2565 mnScrollFlags( 0 )
2569 void XclImpTbxObjScrollableBase::ReadSbs( XclImpStream& rStrm )
2571 rStrm.Ignore( 4 );
2572 mnValue = rStrm.ReaduInt16();
2573 mnMin = rStrm.ReaduInt16();
2574 mnMax = rStrm.ReaduInt16();
2575 mnStep = rStrm.ReaduInt16();
2576 mnPageStep = rStrm.ReaduInt16();
2577 mnOrient = rStrm.ReaduInt16();
2578 mnThumbWidth = rStrm.ReaduInt16();
2579 mnScrollFlags = rStrm.ReaduInt16();
2582 void XclImpTbxObjScrollableBase::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2584 switch( nSubRecId )
2586 case EXC_ID_OBJSBS:
2587 ReadSbs( rStrm );
2588 break;
2589 case EXC_ID_OBJSBSFMLA:
2590 ReadCellLinkFormula( rStrm, false );
2591 break;
2592 default:
2593 XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2597 XclImpSpinButtonObj::XclImpSpinButtonObj( const XclImpRoot& rRoot ) :
2598 XclImpTbxObjScrollableBase( rRoot )
2602 void XclImpSpinButtonObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2604 ReadFrameData( rStrm );
2605 ReadSbs( rStrm );
2606 ReadName5( rStrm, nNameLen );
2607 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2608 ReadCellLinkFormula( rStrm, true );
2611 void XclImpSpinButtonObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2613 // Calc's "Border" property is not the 3D/flat style effect in Excel (#i34712#)
2614 rPropSet.SetProperty( "Border", css::awt::VisualEffect::NONE );
2615 rPropSet.SetProperty< sal_Int32 >( "DefaultSpinValue", mnValue );
2616 rPropSet.SetProperty< sal_Int32 >( "SpinValueMin", mnMin );
2617 rPropSet.SetProperty< sal_Int32 >( "SpinValueMax", mnMax );
2618 rPropSet.SetProperty< sal_Int32 >( "SpinIncrement", mnStep );
2620 // Excel spin buttons always vertical
2621 rPropSet.SetProperty( "Orientation", css::awt::ScrollBarOrientation::VERTICAL );
2624 OUString XclImpSpinButtonObj::DoGetServiceName() const
2626 return "com.sun.star.form.component.SpinButton";
2629 XclTbxEventType XclImpSpinButtonObj::DoGetEventType() const
2631 return EXC_TBX_EVENT_VALUE;
2634 XclImpScrollBarObj::XclImpScrollBarObj( const XclImpRoot& rRoot ) :
2635 XclImpTbxObjScrollableBase( rRoot )
2639 void XclImpScrollBarObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2641 ReadFrameData( rStrm );
2642 ReadSbs( rStrm );
2643 ReadName5( rStrm, nNameLen );
2644 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2645 ReadCellLinkFormula( rStrm, true );
2648 void XclImpScrollBarObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2650 // Calc's "Border" property is not the 3D/flat style effect in Excel (#i34712#)
2651 rPropSet.SetProperty( "Border", css::awt::VisualEffect::NONE );
2652 rPropSet.SetProperty< sal_Int32 >( "DefaultScrollValue", mnValue );
2653 rPropSet.SetProperty< sal_Int32 >( "ScrollValueMin", mnMin );
2654 rPropSet.SetProperty< sal_Int32 >( "ScrollValueMax", mnMax );
2655 rPropSet.SetProperty< sal_Int32 >( "LineIncrement", mnStep );
2656 rPropSet.SetProperty< sal_Int32 >( "BlockIncrement", mnPageStep );
2657 rPropSet.SetProperty( "VisibleSize", ::std::min< sal_Int32 >( mnPageStep, 1 ) );
2659 namespace AwtScrollOrient = ::com::sun::star::awt::ScrollBarOrientation;
2660 sal_Int32 nApiOrient = ::get_flagvalue( mnOrient, EXC_OBJ_SCROLLBAR_HOR, AwtScrollOrient::HORIZONTAL, AwtScrollOrient::VERTICAL );
2661 rPropSet.SetProperty( "Orientation", nApiOrient );
2664 OUString XclImpScrollBarObj::DoGetServiceName() const
2666 return "com.sun.star.form.component.ScrollBar";
2669 XclTbxEventType XclImpScrollBarObj::DoGetEventType() const
2671 return EXC_TBX_EVENT_VALUE;
2674 XclImpTbxObjListBase::XclImpTbxObjListBase( const XclImpRoot& rRoot ) :
2675 XclImpTbxObjScrollableBase( rRoot ),
2676 mnEntryCount( 0 ),
2677 mnSelEntry( 0 ),
2678 mnListFlags( 0 ),
2679 mnEditObjId( 0 ),
2680 mbHasDefFontIdx( false )
2684 void XclImpTbxObjListBase::ReadLbsData( XclImpStream& rStrm )
2686 ReadSourceRangeFormula( rStrm, true );
2687 mnEntryCount = rStrm.ReaduInt16();
2688 mnSelEntry = rStrm.ReaduInt16();
2689 mnListFlags = rStrm.ReaduInt16();
2690 mnEditObjId = rStrm.ReaduInt16();
2693 void XclImpTbxObjListBase::SetBoxFormatting( ScfPropertySet& rPropSet ) const
2695 // border style
2696 namespace AwtVisualEffect = ::com::sun::star::awt::VisualEffect;
2697 sal_Int16 nApiBorder = ::get_flagvalue( mnListFlags, EXC_OBJ_LISTBOX_FLAT, AwtVisualEffect::FLAT, AwtVisualEffect::LOOK3D );
2698 rPropSet.SetProperty( "Border", nApiBorder );
2700 // font formatting
2701 if( mbHasDefFontIdx )
2702 GetFontBuffer().WriteFontProperties( rPropSet, EXC_FONTPROPSET_CONTROL, maTextData.maData.mnDefFontIdx );
2703 else
2704 GetFontBuffer().WriteDefaultCtrlFontProperties( rPropSet );
2707 XclImpListBoxObj::XclImpListBoxObj( const XclImpRoot& rRoot ) :
2708 XclImpTbxObjListBase( rRoot )
2712 void XclImpListBoxObj::ReadFullLbsData( XclImpStream& rStrm, std::size_t nRecLeft )
2714 std::size_t nRecEnd = rStrm.GetRecPos() + nRecLeft;
2715 ReadLbsData( rStrm );
2716 OSL_ENSURE( (rStrm.GetRecPos() == nRecEnd) || (rStrm.GetRecPos() + mnEntryCount == nRecEnd),
2717 "XclImpListBoxObj::ReadFullLbsData - invalid size of OBJLBSDATA record" );
2718 while( rStrm.IsValid() && (rStrm.GetRecPos() < nRecEnd) )
2719 maSelection.push_back( rStrm.ReaduInt8() );
2722 void XclImpListBoxObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2724 ReadFrameData( rStrm );
2725 ReadSbs( rStrm );
2726 rStrm.Ignore( 18 );
2727 maTextData.maData.mnDefFontIdx = rStrm.ReaduInt16();
2728 rStrm.Ignore( 4 );
2729 ReadName5( rStrm, nNameLen );
2730 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2731 ReadCellLinkFormula( rStrm, true );
2732 ReadFullLbsData( rStrm, rStrm.GetRecLeft() );
2733 mbHasDefFontIdx = true;
2736 void XclImpListBoxObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2738 switch( nSubRecId )
2740 case EXC_ID_OBJLBSDATA:
2741 ReadFullLbsData( rStrm, nSubRecSize );
2742 break;
2743 default:
2744 XclImpTbxObjListBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2748 void XclImpListBoxObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2750 // listbox formatting
2751 SetBoxFormatting( rPropSet );
2753 // selection type
2754 sal_uInt8 nSelType = ::extract_value< sal_uInt8 >( mnListFlags, 4, 2 );
2755 bool bMultiSel = nSelType != EXC_OBJ_LISTBOX_SINGLE;
2756 rPropSet.SetBoolProperty( "MultiSelection", bMultiSel );
2758 // selection (do not set, if listbox is linked to a cell)
2759 if( !HasCellLink() )
2761 ScfInt16Vec aSelVec;
2763 // multi selection: API expects sequence of list entry indexes
2764 if( bMultiSel )
2766 sal_Int16 nIndex = 0;
2767 for( const auto& rItem : maSelection )
2769 if( rItem != 0 )
2770 aSelVec.push_back( nIndex );
2771 ++nIndex;
2774 // single selection: mnSelEntry is one-based, API expects zero-based
2775 else if( mnSelEntry > 0 )
2776 aSelVec.push_back( static_cast< sal_Int16 >( mnSelEntry - 1 ) );
2778 if( !aSelVec.empty() )
2780 Sequence<sal_Int16> aSelSeq(aSelVec.data(), static_cast<sal_Int32>(aSelVec.size()));
2781 rPropSet.SetProperty( "DefaultSelection", aSelSeq );
2786 OUString XclImpListBoxObj::DoGetServiceName() const
2788 return "com.sun.star.form.component.ListBox";
2791 XclTbxEventType XclImpListBoxObj::DoGetEventType() const
2793 return EXC_TBX_EVENT_CHANGE;
2796 XclImpDropDownObj::XclImpDropDownObj( const XclImpRoot& rRoot ) :
2797 XclImpTbxObjListBase( rRoot ),
2798 mnLeft( 0 ),
2799 mnTop( 0 ),
2800 mnRight( 0 ),
2801 mnBottom( 0 ),
2802 mnDropDownFlags( 0 ),
2803 mnLineCount( 0 ),
2804 mnMinWidth( 0 )
2808 sal_uInt16 XclImpDropDownObj::GetDropDownType() const
2810 return ::extract_value< sal_uInt8 >( mnDropDownFlags, 0, 2 );
2813 void XclImpDropDownObj::ReadFullLbsData( XclImpStream& rStrm )
2815 ReadLbsData( rStrm );
2816 mnDropDownFlags = rStrm.ReaduInt16();
2817 mnLineCount = rStrm.ReaduInt16();
2818 mnMinWidth = rStrm.ReaduInt16();
2819 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2820 maTextData.ReadByteString( rStrm );
2821 // dropdowns of auto-filters have 'simple' style, they don't have a text area
2822 if( GetDropDownType() == EXC_OBJ_DROPDOWN_SIMPLE )
2823 SetProcessSdrObj( false );
2826 void XclImpDropDownObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2828 ReadFrameData( rStrm );
2829 ReadSbs( rStrm );
2830 rStrm.Ignore( 18 );
2831 maTextData.maData.mnDefFontIdx = rStrm.ReaduInt16();
2832 rStrm.Ignore( 14 );
2833 mnLeft = rStrm.ReaduInt16();
2834 mnTop = rStrm.ReaduInt16();
2835 mnRight = rStrm.ReaduInt16();
2836 mnBottom = rStrm.ReaduInt16();
2837 rStrm.Ignore( 4 );
2838 ReadName5( rStrm, nNameLen );
2839 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2840 ReadCellLinkFormula( rStrm, true );
2841 ReadFullLbsData( rStrm );
2842 mbHasDefFontIdx = true;
2845 void XclImpDropDownObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2847 switch( nSubRecId )
2849 case EXC_ID_OBJLBSDATA:
2850 ReadFullLbsData( rStrm );
2851 break;
2852 default:
2853 XclImpTbxObjListBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2857 void XclImpDropDownObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2859 // dropdown listbox formatting
2860 SetBoxFormatting( rPropSet );
2861 // enable dropdown button
2862 rPropSet.SetBoolProperty( "Dropdown", true );
2863 // dropdown line count
2864 rPropSet.SetProperty( "LineCount", mnLineCount );
2866 if( GetDropDownType() == EXC_OBJ_DROPDOWN_COMBOBOX )
2868 // text of editable combobox
2869 if( maTextData.mxString )
2870 rPropSet.SetStringProperty( "DefaultText", maTextData.mxString->GetText() );
2872 else
2874 // selection (do not set, if dropdown is linked to a cell)
2875 if( !HasCellLink() && (mnSelEntry > 0) )
2877 Sequence< sal_Int16 > aSelSeq( 1 );
2878 aSelSeq[ 0 ] = mnSelEntry - 1;
2879 rPropSet.SetProperty( "DefaultSelection", aSelSeq );
2884 OUString XclImpDropDownObj::DoGetServiceName() const
2886 return (GetDropDownType() == EXC_OBJ_DROPDOWN_COMBOBOX) ?
2887 OUString( "com.sun.star.form.component.ComboBox" ) :
2888 OUString( "com.sun.star.form.component.ListBox" );
2891 XclTbxEventType XclImpDropDownObj::DoGetEventType() const
2893 return (GetDropDownType() == EXC_OBJ_DROPDOWN_COMBOBOX) ? EXC_TBX_EVENT_TEXT : EXC_TBX_EVENT_CHANGE;
2896 XclImpPictureObj::XclImpPictureObj( const XclImpRoot& rRoot ) :
2897 XclImpRectObj( rRoot ),
2898 XclImpControlHelper( rRoot, EXC_CTRL_BINDCONTENT ),
2899 mnStorageId( 0 ),
2900 mnCtlsStrmPos( 0 ),
2901 mnCtlsStrmSize( 0 ),
2902 mbEmbedded( false ),
2903 mbLinked( false ),
2904 mbSymbol( false ),
2905 mbControl( false ),
2906 mbUseCtlsStrm( false )
2908 SetAreaObj( true );
2909 SetSimpleMacro( true );
2910 SetCustomDffObj( true );
2913 OUString XclImpPictureObj::GetOleStorageName() const
2915 OUStringBuffer aStrgName;
2916 if( (mbEmbedded || mbLinked) && !mbControl && (mnStorageId > 0) )
2918 aStrgName = mbEmbedded ? OUStringLiteral(EXC_STORAGE_OLE_EMBEDDED) : OUStringLiteral(EXC_STORAGE_OLE_LINKED);
2919 static const sal_Char spcHexChars[] = "0123456789ABCDEF";
2920 for( sal_uInt8 nIndex = 32; nIndex > 0; nIndex -= 4 )
2921 aStrgName.append(OUStringChar( spcHexChars[ ::extract_value< sal_uInt8 >( mnStorageId, nIndex - 4, 4 ) ] ));
2923 return aStrgName.makeStringAndClear();
2926 void XclImpPictureObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
2928 sal_uInt16 nLinkSize;
2929 ReadFrameData( rStrm );
2930 rStrm.Ignore( 6 );
2931 nLinkSize = rStrm.ReaduInt16();
2932 rStrm.Ignore( 2 );
2933 ReadFlags3( rStrm );
2934 ReadMacro3( rStrm, nMacroSize );
2935 ReadPictFmla( rStrm, nLinkSize );
2937 if( (rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord() )
2938 maGraphic = XclImpDrawing::ReadImgData( GetRoot(), rStrm );
2941 void XclImpPictureObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
2943 sal_uInt16 nLinkSize;
2944 ReadFrameData( rStrm );
2945 rStrm.Ignore( 6 );
2946 nLinkSize = rStrm.ReaduInt16();
2947 rStrm.Ignore( 2 );
2948 ReadFlags3( rStrm );
2949 ReadMacro4( rStrm, nMacroSize );
2950 ReadPictFmla( rStrm, nLinkSize );
2952 if( (rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord() )
2953 maGraphic = XclImpDrawing::ReadImgData( GetRoot(), rStrm );
2956 void XclImpPictureObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
2958 sal_uInt16 nLinkSize;
2959 ReadFrameData( rStrm );
2960 rStrm.Ignore( 6 );
2961 nLinkSize = rStrm.ReaduInt16();
2962 rStrm.Ignore( 2 );
2963 ReadFlags3( rStrm );
2964 rStrm.Ignore( 4 );
2965 ReadName5( rStrm, nNameLen );
2966 ReadMacro5( rStrm, nMacroSize );
2967 ReadPictFmla( rStrm, nLinkSize );
2969 if( (rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord() )
2971 // page background is stored as hidden picture with name "__BkgndObj"
2972 if ( IsHidden() && (GetObjName() == "__BkgndObj") )
2973 GetPageSettings().ReadImgData( rStrm );
2974 else
2975 maGraphic = XclImpDrawing::ReadImgData( GetRoot(), rStrm );
2979 void XclImpPictureObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2981 switch( nSubRecId )
2983 case EXC_ID_OBJFLAGS:
2984 ReadFlags8( rStrm );
2985 break;
2986 case EXC_ID_OBJPICTFMLA:
2987 ReadPictFmla( rStrm, rStrm.ReaduInt16() );
2988 break;
2989 default:
2990 XclImpDrawObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2994 SdrObjectUniquePtr XclImpPictureObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
2996 // try to create an OLE object or form control
2997 SdrObjectUniquePtr xSdrObj( rDffConv.CreateSdrObject( *this, rAnchorRect ) );
2999 // insert a graphic replacement for unsupported ole object ( if none already
3000 // exists ) Hmm ok, it's possibly that there has been some imported
3001 // graphic at a base level but unlikely, normally controls have a valid
3002 // preview in the IMGDATA record ( see below )
3003 // It might be possible to push such an imported graphic up to this
3004 // XclImpPictureObj instance but there are so many layers of indirection I
3005 // don't see an easy way. This way at least ensures that we can
3006 // avoid a 'blank' shape that can result from a failed control import
3007 if ( !xSdrObj && IsOcxControl() && maGraphic.GetType() == GraphicType::NONE )
3009 const_cast< XclImpPictureObj* >( this )->maGraphic =
3010 SdrOle2Obj::GetEmptyOLEReplacementGraphic();
3012 // no OLE - create a plain picture from IMGDATA record data
3013 if( !xSdrObj && (maGraphic.GetType() != GraphicType::NONE) )
3015 xSdrObj.reset(
3016 new SdrGrafObj(
3017 *GetDoc().GetDrawLayer(),
3018 maGraphic,
3019 rAnchorRect));
3020 ConvertRectStyle( *xSdrObj );
3023 rDffConv.Progress();
3024 return xSdrObj;
3027 OUString XclImpPictureObj::GetObjName() const
3029 if( IsOcxControl() )
3031 OUString sName( GetObjectManager().GetOleNameOverride( GetTab(), GetObjId() ) );
3032 if (!sName.isEmpty())
3033 return sName;
3035 return XclImpDrawObjBase::GetObjName();
3038 void XclImpPictureObj::DoPreProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const
3040 if( IsOcxControl() )
3042 // do not call XclImpRectObj::DoPreProcessSdrObj(), it would trace missing "printable" feature
3043 ProcessControl( *this );
3045 else if( mbEmbedded || mbLinked )
3047 // trace missing "printable" feature
3048 XclImpRectObj::DoPreProcessSdrObj( rDffConv, rSdrObj );
3050 SfxObjectShell* pDocShell = GetDocShell();
3051 SdrOle2Obj* pOleSdrObj = dynamic_cast< SdrOle2Obj* >( &rSdrObj );
3052 if( pOleSdrObj && pDocShell )
3054 comphelper::EmbeddedObjectContainer& rEmbObjCont = pDocShell->GetEmbeddedObjectContainer();
3055 Reference< XEmbeddedObject > xEmbObj = pOleSdrObj->GetObjRef();
3056 OUString aOldName( pOleSdrObj->GetPersistName() );
3058 /* The object persistence should be already in the storage, but
3059 the object still might not be inserted into the container. */
3060 if( rEmbObjCont.HasEmbeddedObject( aOldName ) )
3062 if( !rEmbObjCont.HasEmbeddedObject( xEmbObj ) )
3063 // filter code is allowed to call the following method
3064 rEmbObjCont.AddEmbeddedObject( xEmbObj, aOldName );
3066 else
3068 /* If the object is still not in container it must be inserted
3069 there, the name must be generated in this case. */
3070 OUString aNewName;
3071 rEmbObjCont.InsertEmbeddedObject( xEmbObj, aNewName );
3072 if( aOldName != aNewName )
3073 // SetPersistName, not SetName
3074 pOleSdrObj->SetPersistName( aNewName );
3080 void XclImpPictureObj::ReadFlags3( XclImpStream& rStrm )
3082 sal_uInt16 nFlags;
3083 nFlags = rStrm.ReaduInt16();
3084 mbSymbol = ::get_flag( nFlags, EXC_OBJ_PIC_SYMBOL );
3087 void XclImpPictureObj::ReadFlags8( XclImpStream& rStrm )
3089 sal_uInt16 nFlags;
3090 nFlags = rStrm.ReaduInt16();
3091 mbSymbol = ::get_flag( nFlags, EXC_OBJ_PIC_SYMBOL );
3092 mbControl = ::get_flag( nFlags, EXC_OBJ_PIC_CONTROL );
3093 mbUseCtlsStrm = ::get_flag( nFlags, EXC_OBJ_PIC_CTLSSTREAM );
3094 OSL_ENSURE( mbControl || !mbUseCtlsStrm, "XclImpPictureObj::ReadFlags8 - CTLS stream for controls only" );
3095 SetProcessSdrObj( mbControl || !mbUseCtlsStrm );
3098 void XclImpPictureObj::ReadPictFmla( XclImpStream& rStrm, sal_uInt16 nLinkSize )
3100 std::size_t nLinkEnd = rStrm.GetRecPos() + nLinkSize;
3101 if( nLinkSize >= 6 )
3103 sal_uInt16 nFmlaSize;
3104 nFmlaSize = rStrm.ReaduInt16();
3105 OSL_ENSURE( nFmlaSize > 0, "XclImpPictureObj::ReadPictFmla - missing link formula" );
3106 // BIFF3/BIFF4 do not support storages, nothing to do here
3107 if( (nFmlaSize > 0) && (GetBiff() >= EXC_BIFF5) )
3109 rStrm.Ignore( 4 );
3110 sal_uInt8 nToken;
3111 nToken = rStrm.ReaduInt8();
3113 // different processing for linked vs. embedded OLE objects
3114 if( nToken == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ) )
3116 mbLinked = true;
3117 switch( GetBiff() )
3119 case EXC_BIFF5:
3121 sal_Int16 nRefIdx;
3122 sal_uInt16 nNameIdx;
3123 nRefIdx = rStrm.ReadInt16();
3124 rStrm.Ignore( 8 );
3125 nNameIdx = rStrm.ReaduInt16();
3126 rStrm.Ignore( 12 );
3127 const ExtName* pExtName = GetOldRoot().pExtNameBuff->GetNameByIndex( nRefIdx, nNameIdx );
3128 if( pExtName && pExtName->IsOLE() )
3129 mnStorageId = pExtName->nStorageId;
3131 break;
3132 case EXC_BIFF8:
3134 sal_uInt16 nXti, nExtName;
3135 nXti = rStrm.ReaduInt16();
3136 nExtName = rStrm.ReaduInt16();
3137 const XclImpExtName* pExtName = GetLinkManager().GetExternName( nXti, nExtName );
3138 if( pExtName && (pExtName->GetType() == xlExtOLE) )
3139 mnStorageId = pExtName->GetStorageId();
3141 break;
3142 default:
3143 DBG_ERROR_BIFF();
3146 else if( nToken == XclTokenArrayHelper::GetTokenId( EXC_TOKID_TBL, EXC_TOKCLASS_NONE ) )
3148 mbEmbedded = true;
3149 OSL_ENSURE( nFmlaSize == 5, "XclImpPictureObj::ReadPictFmla - unexpected formula size" );
3150 rStrm.Ignore( nFmlaSize - 1 ); // token ID already read
3151 if( nFmlaSize & 1 )
3152 rStrm.Ignore( 1 ); // padding byte
3154 // a class name may follow inside the picture link
3155 if( rStrm.GetRecPos() + 2 <= nLinkEnd )
3157 sal_uInt16 nLen = rStrm.ReaduInt16();
3158 if( nLen > 0 )
3159 maClassName = (GetBiff() == EXC_BIFF8) ? rStrm.ReadUniString( nLen ) : rStrm.ReadRawByteString( nLen );
3162 // else: ignore other formulas, e.g. pictures linked to cell ranges
3166 // seek behind picture link data
3167 rStrm.Seek( nLinkEnd );
3169 // read additional data for embedded OLE objects following the picture link
3170 if( IsOcxControl() )
3172 // #i26521# form controls to be ignored
3173 if( maClassName == "Forms.HTML:Hidden.1" )
3175 SetProcessSdrObj( false );
3176 return;
3179 if( rStrm.GetRecLeft() <= 8 ) return;
3181 // position and size of control data in 'Ctls' stream
3182 mnCtlsStrmPos = static_cast< std::size_t >( rStrm.ReaduInt32() );
3183 mnCtlsStrmSize = static_cast< std::size_t >( rStrm.ReaduInt32() );
3185 if( rStrm.GetRecLeft() <= 8 ) return;
3187 // additional string (16-bit characters), e.g. for progress bar control
3188 sal_uInt32 nAddStrSize;
3189 nAddStrSize = rStrm.ReaduInt32();
3190 OSL_ENSURE( rStrm.GetRecLeft() >= nAddStrSize + 4, "XclImpPictureObj::ReadPictFmla - missing data" );
3191 if( rStrm.GetRecLeft() >= nAddStrSize + 4 )
3193 rStrm.Ignore( nAddStrSize );
3194 // cell link and source range
3195 ReadCellLinkFormula( rStrm, true );
3196 ReadSourceRangeFormula( rStrm, true );
3199 else if( mbEmbedded && (rStrm.GetRecLeft() >= 4) )
3201 mnStorageId = rStrm.ReaduInt32();
3205 // DFF stream conversion ======================================================
3207 void XclImpSolverContainer::InsertSdrObjectInfo( SdrObject& rSdrObj, sal_uInt32 nDffShapeId, ShapeFlag nDffFlags )
3209 if( nDffShapeId > 0 )
3211 maSdrInfoMap[ nDffShapeId ].Set( &rSdrObj, nDffFlags );
3212 maSdrObjMap[ &rSdrObj ] = nDffShapeId;
3216 void XclImpSolverContainer::RemoveSdrObjectInfo( SdrObject& rSdrObj )
3218 // remove info of passed object from the maps
3219 XclImpSdrObjMap::iterator aIt = maSdrObjMap.find( &rSdrObj );
3220 if( aIt != maSdrObjMap.end() )
3222 maSdrInfoMap.erase( aIt->second );
3223 maSdrObjMap.erase( aIt );
3226 // remove info of all child objects of a group object
3227 if( SdrObjGroup* pGroupObj = dynamic_cast< SdrObjGroup* >( &rSdrObj ) )
3229 if( SdrObjList* pSubList = pGroupObj->GetSubList() )
3231 // iterate flat over the list because this function already works recursively
3232 SdrObjListIter aObjIt( pSubList, SdrIterMode::Flat );
3233 for( SdrObject* pChildObj = aObjIt.Next(); pChildObj; pChildObj = aObjIt.Next() )
3234 RemoveSdrObjectInfo( *pChildObj );
3239 void XclImpSolverContainer::UpdateConnectorRules()
3241 for (auto const & pRule : aCList)
3243 UpdateConnection( pRule->nShapeA, pRule->pAObj, &pRule->nSpFlagsA );
3244 UpdateConnection( pRule->nShapeB, pRule->pBObj, &pRule->nSpFlagsB );
3245 UpdateConnection( pRule->nShapeC, pRule->pCObj );
3249 void XclImpSolverContainer::RemoveConnectorRules()
3251 aCList.clear();
3252 maSdrInfoMap.clear();
3253 maSdrObjMap.clear();
3256 void XclImpSolverContainer::UpdateConnection( sal_uInt32 nDffShapeId, SdrObject*& rpSdrObj, ShapeFlag* pnDffFlags )
3258 XclImpSdrInfoMap::const_iterator aIt = maSdrInfoMap.find( nDffShapeId );
3259 if( aIt != maSdrInfoMap.end() )
3261 rpSdrObj = aIt->second.mpSdrObj;
3262 if( pnDffFlags )
3263 *pnDffFlags = aIt->second.mnDffFlags;
3267 XclImpSimpleDffConverter::XclImpSimpleDffConverter( const XclImpRoot& rRoot, SvStream& rDffStrm ) :
3268 SvxMSDffManager( rDffStrm, rRoot.GetBasePath(), 0, nullptr, rRoot.GetDoc().GetDrawLayer(), 1440, COL_DEFAULT, nullptr ),
3269 XclImpRoot( rRoot )
3271 SetSvxMSDffSettings( SVXMSDFF_SETTINGS_CROP_BITMAPS | SVXMSDFF_SETTINGS_IMPORT_EXCEL );
3274 XclImpSimpleDffConverter::~XclImpSimpleDffConverter()
3278 bool XclImpSimpleDffConverter::GetColorFromPalette( sal_uInt16 nIndex, Color& rColor ) const
3280 Color nColor = GetPalette().GetColor( nIndex );
3282 if( nColor == COL_AUTO )
3283 return false;
3285 rColor = nColor;
3286 return true;
3289 XclImpDffConverter::XclImpDffConvData::XclImpDffConvData(
3290 XclImpDrawing& rDrawing, SdrModel& rSdrModel, SdrPage& rSdrPage ) :
3291 mrDrawing( rDrawing ),
3292 mrSdrModel( rSdrModel ),
3293 mrSdrPage( rSdrPage ),
3294 mnLastCtrlIndex( -1 ),
3295 mbHasCtrlForm( false )
3299 static const OUStringLiteral gaStdFormName( "Standard" ); /// Standard name of control forms.
3301 XclImpDffConverter::XclImpDffConverter( const XclImpRoot& rRoot, SvStream& rDffStrm ) :
3302 XclImpSimpleDffConverter( rRoot, rDffStrm ),
3303 oox::ole::MSConvertOCXControls( rRoot.GetDocShell()->GetModel() ),
3304 mnOleImpFlags( 0 ),
3305 mbNotifyMacroEventRead(false)
3307 const SvtFilterOptions& rFilterOpt = SvtFilterOptions::Get();
3308 if( rFilterOpt.IsMathType2Math() )
3309 mnOleImpFlags |= OLE_MATHTYPE_2_STARMATH;
3310 if( rFilterOpt.IsWinWord2Writer() )
3311 mnOleImpFlags |= OLE_WINWORD_2_STARWRITER;
3312 if( rFilterOpt.IsPowerPoint2Impress() )
3313 mnOleImpFlags |= OLE_POWERPOINT_2_STARIMPRESS;
3315 // try to open the 'Ctls' storage stream containing OCX control properties
3316 mxCtlsStrm = OpenStream( EXC_STREAM_CTLS );
3318 // default text margin (convert EMU to drawing layer units)
3319 mnDefTextMargin = EXC_OBJ_TEXT_MARGIN;
3320 ScaleEmu( mnDefTextMargin );
3323 XclImpDffConverter::~XclImpDffConverter()
3327 OUString XclImpObjectManager::GetOleNameOverride( SCTAB nTab, sal_uInt16 nObjId )
3329 OUString sOleName;
3330 OUString sCodeName = GetExtDocOptions().GetCodeName( nTab );
3332 if (mxOleCtrlNameOverride.is() && mxOleCtrlNameOverride->hasByName(sCodeName))
3334 Reference< XIndexContainer > xIdToOleName;
3335 mxOleCtrlNameOverride->getByName( sCodeName ) >>= xIdToOleName;
3336 xIdToOleName->getByIndex( nObjId ) >>= sOleName;
3339 return sOleName;
3342 void XclImpDffConverter::StartProgressBar( std::size_t nProgressSize )
3344 mxProgress.reset( new ScfProgressBar( GetDocShell(), STR_PROGRESS_CALCULATING ) );
3345 mxProgress->AddSegment( nProgressSize );
3346 mxProgress->Activate();
3349 void XclImpDffConverter::Progress( std::size_t nDelta )
3351 OSL_ENSURE( mxProgress, "XclImpDffConverter::Progress - invalid call, no progress bar" );
3352 mxProgress->Progress( nDelta );
3355 void XclImpDffConverter::InitializeDrawing( XclImpDrawing& rDrawing, SdrModel& rSdrModel, SdrPage& rSdrPage )
3357 XclImpDffConvDataRef xConvData( new XclImpDffConvData( rDrawing, rSdrModel, rSdrPage ) );
3358 maDataStack.push_back( xConvData );
3359 SetModel( &xConvData->mrSdrModel, 1440 );
3362 void XclImpDffConverter::ProcessObject( SdrObjList& rObjList, XclImpDrawObjBase& rDrawObj )
3364 if( rDrawObj.IsProcessSdrObj() )
3366 if( const XclObjAnchor* pAnchor = rDrawObj.GetAnchor() )
3368 tools::Rectangle aAnchorRect = GetConvData().mrDrawing.CalcAnchorRect( *pAnchor, false );
3369 if( rDrawObj.IsValidSize( aAnchorRect ) )
3371 // CreateSdrObject() recursively creates embedded child objects
3372 SdrObjectUniquePtr xSdrObj( rDrawObj.CreateSdrObject( *this, aAnchorRect, false ) );
3373 if( xSdrObj )
3374 rDrawObj.PreProcessSdrObject( *this, *xSdrObj );
3375 // call InsertSdrObject() also, if SdrObject is missing
3376 InsertSdrObject( rObjList, rDrawObj, xSdrObj.release() );
3382 void XclImpDffConverter::ProcessDrawing( const XclImpDrawObjVector& rDrawObjs )
3384 SdrPage& rSdrPage = GetConvData().mrSdrPage;
3385 for( const auto& rxDrawObj : rDrawObjs )
3386 ProcessObject( rSdrPage, *rxDrawObj );
3389 void XclImpDffConverter::ProcessDrawing( SvStream& rDffStrm )
3391 if( rDffStrm.TellEnd() > 0 )
3393 rDffStrm.Seek( STREAM_SEEK_TO_BEGIN );
3394 DffRecordHeader aHeader;
3395 ReadDffRecordHeader( rDffStrm, aHeader );
3396 OSL_ENSURE( aHeader.nRecType == DFF_msofbtDgContainer, "XclImpDffConverter::ProcessDrawing - unexpected record" );
3397 if( aHeader.nRecType == DFF_msofbtDgContainer )
3398 ProcessDgContainer( rDffStrm, aHeader );
3402 void XclImpDffConverter::FinalizeDrawing()
3404 OSL_ENSURE( !maDataStack.empty(), "XclImpDffConverter::FinalizeDrawing - no drawing manager on stack" );
3405 maDataStack.pop_back();
3406 // restore previous model at core DFF converter
3407 if( !maDataStack.empty() )
3408 SetModel( &maDataStack.back()->mrSdrModel, 1440 );
3411 void XclImpDffConverter::NotifyMacroEventRead()
3413 if (mbNotifyMacroEventRead)
3414 return;
3415 comphelper::DocumentInfo::notifyMacroEventRead(mxModel);
3416 mbNotifyMacroEventRead = true;
3419 SdrObjectUniquePtr XclImpDffConverter::CreateSdrObject( const XclImpTbxObjBase& rTbxObj, const tools::Rectangle& rAnchorRect )
3421 SdrObjectUniquePtr xSdrObj;
3423 OUString aServiceName = rTbxObj.GetServiceName();
3424 if( SupportsOleObjects() && !aServiceName.isEmpty() ) try
3426 // create the form control from scratch
3427 Reference< XFormComponent > xFormComp( ScfApiHelper::CreateInstance( GetDocShell(), aServiceName ), UNO_QUERY_THROW );
3428 // set controls form, needed in virtual function InsertControl()
3429 InitControlForm();
3430 // try to insert the control into the form
3431 css::awt::Size aDummySize;
3432 Reference< XShape > xShape;
3433 XclImpDffConvData& rConvData = GetConvData();
3434 if( rConvData.mxCtrlForm.is() && InsertControl( xFormComp, aDummySize, &xShape, true ) )
3436 xSdrObj = rTbxObj.CreateSdrObjectFromShape( xShape, rAnchorRect );
3437 // try to attach a macro to the control
3438 ScriptEventDescriptor aDescriptor;
3439 if( (rConvData.mnLastCtrlIndex >= 0) && rTbxObj.FillMacroDescriptor( aDescriptor ) )
3441 NotifyMacroEventRead();
3442 Reference< XEventAttacherManager > xEventMgr( rConvData.mxCtrlForm, UNO_QUERY_THROW );
3443 xEventMgr->registerScriptEvent( rConvData.mnLastCtrlIndex, aDescriptor );
3447 catch( const Exception& )
3451 return xSdrObj;
3454 SdrObjectUniquePtr XclImpDffConverter::CreateSdrObject( const XclImpPictureObj& rPicObj, const tools::Rectangle& rAnchorRect )
3456 SdrObjectUniquePtr xSdrObj;
3458 if( SupportsOleObjects() )
3460 if( rPicObj.IsOcxControl() )
3462 if( mxCtlsStrm.is() ) try
3464 /* set controls form, needed in virtual function InsertControl()
3465 called from ReadOCXExcelKludgeStream() */
3466 InitControlForm();
3468 // read from mxCtlsStrm into xShape, insert the control model into the form
3469 Reference< XShape > xShape;
3470 if( GetConvData().mxCtrlForm.is() )
3472 Reference< XFormComponent > xFComp;
3473 css::awt::Size aSz; // not used in import
3474 ReadOCXCtlsStream( mxCtlsStrm, xFComp, rPicObj.GetCtlsStreamPos(), rPicObj.GetCtlsStreamSize() );
3475 // recreate the method formerly known as ReadOCXExcelKludgeStream()
3476 if ( xFComp.is() )
3478 ScfPropertySet aPropSet( xFComp );
3479 aPropSet.SetStringProperty( "Name", rPicObj.GetObjName() );
3480 InsertControl( xFComp, aSz,&xShape,true);
3481 xSdrObj = rPicObj.CreateSdrObjectFromShape( xShape, rAnchorRect );
3485 catch( const Exception& )
3489 else
3491 SfxObjectShell* pDocShell = GetDocShell();
3492 tools::SvRef<SotStorage> xSrcStrg = GetRootStorage();
3493 OUString aStrgName = rPicObj.GetOleStorageName();
3494 if( pDocShell && xSrcStrg.is() && (!aStrgName.isEmpty()) )
3496 // first try to resolve graphic from DFF storage
3497 Graphic aGraphic;
3498 tools::Rectangle aVisArea;
3499 if( !GetBLIP( GetPropertyValue( DFF_Prop_pib, 0 ), aGraphic, &aVisArea ) )
3501 // if not found, use graphic from object (imported from IMGDATA record)
3502 aGraphic = rPicObj.GetGraphic();
3504 if( aGraphic.GetType() != GraphicType::NONE )
3506 ErrCode nError = ERRCODE_NONE;
3507 namespace cssea = ::com::sun::star::embed::Aspects;
3508 sal_Int64 nAspects = rPicObj.IsSymbol() ? cssea::MSOLE_ICON : cssea::MSOLE_CONTENT;
3509 xSdrObj.reset(
3510 CreateSdrOLEFromStorage(
3511 GetConvData().mrSdrModel,
3512 aStrgName,
3513 xSrcStrg,
3514 pDocShell->GetStorage(),
3515 aGraphic,
3516 rAnchorRect,
3517 aVisArea,
3518 nullptr,
3519 nError,
3520 mnOleImpFlags,
3521 nAspects,
3522 GetRoot().GetMedium().GetBaseURL()));
3528 return xSdrObj;
3531 bool XclImpDffConverter::SupportsOleObjects() const
3533 return GetConvData().mrDrawing.SupportsOleObjects();
3536 // virtual functions ----------------------------------------------------------
3538 void XclImpDffConverter::ProcessClientAnchor2( SvStream& rDffStrm,
3539 DffRecordHeader& rHeader, DffObjData& rObjData )
3541 // find the OBJ record data related to the processed shape
3542 XclImpDffConvData& rConvData = GetConvData();
3543 if( XclImpDrawObjBase* pDrawObj = rConvData.mrDrawing.FindDrawObj( rObjData.rSpHd ).get() )
3545 OSL_ENSURE( rHeader.nRecType == DFF_msofbtClientAnchor, "XclImpDffConverter::ProcessClientAnchor2 - no client anchor record" );
3546 XclObjAnchor aAnchor;
3547 rHeader.SeekToContent( rDffStrm );
3548 sal_uInt8 nFlags(0);
3549 rDffStrm.ReadUChar( nFlags );
3550 rDffStrm.SeekRel( 1 ); // flags
3551 rDffStrm >> aAnchor; // anchor format equal to BIFF5 OBJ records
3553 pDrawObj->SetAnchor( aAnchor );
3554 rObjData.aChildAnchor = rConvData.mrDrawing.CalcAnchorRect( aAnchor, true );
3555 rObjData.bChildAnchor = true;
3556 // page anchoring is the best approximation we have if mbMove
3557 // is set
3558 rObjData.bPageAnchor = ( nFlags & 0x1 );
3562 struct XclImpDrawObjClientData : public SvxMSDffClientData
3564 const XclImpDrawObjBase* m_pTopLevelObj;
3566 XclImpDrawObjClientData()
3567 : m_pTopLevelObj(nullptr)
3570 virtual void NotifyFreeObj(SdrObject*) override {}
3573 SdrObject* XclImpDffConverter::ProcessObj( SvStream& rDffStrm, DffObjData& rDffObjData,
3574 SvxMSDffClientData& rClientData, tools::Rectangle& /*rTextRect*/, SdrObject* pOldSdrObj )
3576 XclImpDffConvData& rConvData = GetConvData();
3578 /* pOldSdrObj passes a generated SdrObject. This function owns this object
3579 and can modify it. The function has either to return it back to caller
3580 or to delete it by itself. */
3581 SdrObjectUniquePtr xSdrObj( pOldSdrObj );
3583 // find the OBJ record data related to the processed shape
3584 XclImpDrawObjRef xDrawObj = rConvData.mrDrawing.FindDrawObj( rDffObjData.rSpHd );
3585 const tools::Rectangle& rAnchorRect = rDffObjData.aChildAnchor;
3587 // Do not process the global page group shape
3588 bool bGlobalPageGroup( rDffObjData.nSpFlags & ShapeFlag::Patriarch );
3589 if( !xDrawObj || !xDrawObj->IsProcessSdrObj() || bGlobalPageGroup )
3590 return nullptr; // simply return, xSdrObj will be destroyed
3592 /* Pass pointer to top-level object back to caller. If the processed
3593 object is embedded in a group, the pointer is already set to the
3594 top-level parent object. */
3595 XclImpDrawObjClientData& rDrawObjClientData = static_cast<XclImpDrawObjClientData&>(rClientData);
3596 const bool bIsTopLevel = !rDrawObjClientData.m_pTopLevelObj;
3597 if (bIsTopLevel )
3598 rDrawObjClientData.m_pTopLevelObj = xDrawObj.get();
3600 // connectors don't have to be area objects
3601 if( dynamic_cast< SdrEdgeObj* >( xSdrObj.get() ) )
3602 xDrawObj->SetAreaObj( false );
3604 /* Check for valid size for all objects. Needed to ignore lots of invisible
3605 phantom objects from deleted rows or columns (for performance reasons).
3606 #i30816# Include objects embedded in groups.
3607 #i58780# Ignore group shapes, size is not initialized. */
3608 bool bEmbeddedGroup = !bIsTopLevel && dynamic_cast< SdrObjGroup* >( xSdrObj.get() );
3609 if( !bEmbeddedGroup && !xDrawObj->IsValidSize( rAnchorRect ) )
3610 return nullptr; // simply return, xSdrObj will be destroyed
3612 // set shape information from DFF stream
3613 OUString aObjName = GetPropertyString( DFF_Prop_wzName, rDffStrm );
3614 OUString aHyperlink = ReadHlinkProperty( rDffStrm );
3615 bool bVisible = !GetPropertyBool( DFF_Prop_fHidden );
3616 bool bAutoMargin = GetPropertyBool( DFF_Prop_AutoTextMargin );
3617 xDrawObj->SetDffData( rDffObjData, aObjName, aHyperlink, bVisible, bAutoMargin );
3619 /* Connect textbox data (string, alignment, text orientation) to object.
3620 don't ask for a text-ID, DFF export doesn't set one. */
3621 if( XclImpTextObj* pTextObj = dynamic_cast< XclImpTextObj* >( xDrawObj.get() ) )
3622 if( const XclImpObjTextData* pTextData = rConvData.mrDrawing.FindTextData( rDffObjData.rSpHd ) )
3623 pTextObj->SetTextData( *pTextData );
3625 // copy line and fill formatting of TBX form controls from DFF properties
3626 if( XclImpTbxObjBase* pTbxObj = dynamic_cast< XclImpTbxObjBase* >( xDrawObj.get() ) )
3627 pTbxObj->SetDffProperties( *this );
3629 // try to create a custom SdrObject that overwrites the passed object
3630 SdrObjectUniquePtr xNewSdrObj( xDrawObj->CreateSdrObject( *this, rAnchorRect, true ) );
3631 if( xNewSdrObj )
3632 xSdrObj = std::move( xNewSdrObj );
3634 // process the SdrObject
3635 if( xSdrObj )
3637 // filled without color -> set system window color
3638 if( GetPropertyBool( DFF_Prop_fFilled ) && !IsProperty( DFF_Prop_fillColor ) )
3639 xSdrObj->SetMergedItem( XFillColorItem( EMPTY_OUSTRING, GetPalette().GetColor( EXC_COLOR_WINDOWBACK ) ) );
3641 // additional processing on the SdrObject
3642 xDrawObj->PreProcessSdrObject( *this, *xSdrObj );
3644 /* If the SdrObject will not be inserted into the draw page, delete it
3645 here. Happens e.g. for notes: The PreProcessSdrObject() call above
3646 has inserted the note into the document, and the SdrObject is not
3647 needed anymore. */
3648 if( !xDrawObj->IsInsertSdrObj() )
3649 xSdrObj.reset();
3652 if( xSdrObj )
3654 /* Store the relation between shape ID and SdrObject for connectors.
3655 Must be done here (and not in InsertSdrObject() function),
3656 otherwise all SdrObjects embedded in groups would be lost. */
3657 rConvData.maSolverCont.InsertSdrObjectInfo( *xSdrObj, xDrawObj->GetDffShapeId(), xDrawObj->GetDffFlags() );
3659 /* If the drawing object is embedded in a group object, call
3660 PostProcessSdrObject() here. For top-level objects this will be
3661 done automatically in InsertSdrObject() but grouped shapes are
3662 inserted into their groups somewhere in the SvxMSDffManager base
3663 class without chance of notification. Unfortunately, now this is
3664 called before the object is really inserted into its group object,
3665 but that should not have any effect for grouped objects. */
3666 if( !bIsTopLevel )
3667 xDrawObj->PostProcessSdrObject( *this, *xSdrObj );
3670 return xSdrObj.release();
3673 SdrObject* XclImpDffConverter::FinalizeObj(DffObjData& rDffObjData, SdrObject* pOldSdrObj )
3675 XclImpDffConvData& rConvData = GetConvData();
3677 /* pOldSdrObj passes a generated SdrObject. This function owns this object
3678 and can modify it. The function has either to return it back to caller
3679 or to delete it by itself. */
3680 SdrObjectUniquePtr xSdrObj( pOldSdrObj );
3682 // find the OBJ record data related to the processed shape
3683 XclImpDrawObjRef xDrawObj = rConvData.mrDrawing.FindDrawObj( rDffObjData.rSpHd );
3685 if( xSdrObj && xDrawObj )
3687 // cell anchoring
3688 if ( !rDffObjData.bPageAnchor )
3689 ScDrawLayer::SetCellAnchoredFromPosition( *xSdrObj, GetDoc(), xDrawObj->GetTab(), false );
3692 return xSdrObj.release();
3695 bool XclImpDffConverter::InsertControl( const Reference< XFormComponent >& rxFormComp,
3696 const css::awt::Size& /*rSize*/, Reference< XShape >* pxShape,
3697 bool /*bFloatingCtrl*/ )
3699 if( GetDocShell() ) try
3701 XclImpDffConvData& rConvData = GetConvData();
3702 Reference< XIndexContainer > xFormIC( rConvData.mxCtrlForm, UNO_QUERY_THROW );
3703 Reference< XControlModel > xCtrlModel( rxFormComp, UNO_QUERY_THROW );
3705 // create the control shape
3706 Reference< XShape > xShape( ScfApiHelper::CreateInstance( GetDocShell(), "com.sun.star.drawing.ControlShape" ), UNO_QUERY_THROW );
3707 Reference< XControlShape > xCtrlShape( xShape, UNO_QUERY_THROW );
3709 // insert the new control into the form
3710 sal_Int32 nNewIndex = xFormIC->getCount();
3711 xFormIC->insertByIndex( nNewIndex, Any( rxFormComp ) );
3712 // on success: store new index of the control for later use (macro events)
3713 rConvData.mnLastCtrlIndex = nNewIndex;
3715 // set control model at control shape and pass back shape to caller
3716 xCtrlShape->setControl( xCtrlModel );
3717 if( pxShape ) *pxShape = xShape;
3718 return true;
3720 catch( const Exception& )
3722 OSL_FAIL( "XclImpDffConverter::InsertControl - cannot create form control" );
3725 return false;
3728 // private --------------------------------------------------------------------
3730 XclImpDffConverter::XclImpDffConvData& XclImpDffConverter::GetConvData()
3732 OSL_ENSURE( !maDataStack.empty(), "XclImpDffConverter::GetConvData - no drawing manager on stack" );
3733 return *maDataStack.back();
3736 const XclImpDffConverter::XclImpDffConvData& XclImpDffConverter::GetConvData() const
3738 OSL_ENSURE( !maDataStack.empty(), "XclImpDffConverter::GetConvData - no drawing manager on stack" );
3739 return *maDataStack.back();
3742 OUString XclImpDffConverter::ReadHlinkProperty( SvStream& rDffStrm ) const
3744 /* Reads hyperlink data from a complex DFF property. Contents of this
3745 property are equal to the HLINK record, import of this record is
3746 implemented in class XclImpHyperlink. This function has to create an
3747 instance of the XclImpStream class to be able to reuse the
3748 functionality of XclImpHyperlink. */
3749 OUString aString;
3750 sal_uInt32 nBufferSize = GetPropertyValue( DFF_Prop_pihlShape, 0 );
3751 if( (0 < nBufferSize) && (nBufferSize <= 0xFFFF) && SeekToContent( DFF_Prop_pihlShape, rDffStrm ) )
3753 // create a faked BIFF record that can be read by XclImpStream class
3754 SvMemoryStream aMemStream;
3755 aMemStream.WriteUInt16( 0 ).WriteUInt16( nBufferSize );
3757 // copy from DFF stream to memory stream
3758 ::std::vector< sal_uInt8 > aBuffer( nBufferSize );
3759 sal_uInt8* pnData = aBuffer.data();
3760 if (rDffStrm.ReadBytes(pnData, nBufferSize) == nBufferSize)
3762 aMemStream.WriteBytes(pnData, nBufferSize);
3764 // create BIFF import stream to be able to use XclImpHyperlink class
3765 XclImpStream aXclStrm( aMemStream, GetRoot() );
3766 if( aXclStrm.StartNextRecord() )
3767 aString = XclImpHyperlink::ReadEmbeddedData( aXclStrm );
3770 return aString;
3773 bool XclImpDffConverter::ProcessDgContainer( SvStream& rDffStrm, const DffRecordHeader& rDgHeader )
3775 std::size_t nEndPos = rDgHeader.GetRecEndFilePos();
3776 bool isBreak(false);
3777 while (!isBreak && rDffStrm.good() && rDffStrm.Tell() < nEndPos)
3779 DffRecordHeader aHeader;
3780 ReadDffRecordHeader( rDffStrm, aHeader );
3781 switch( aHeader.nRecType )
3783 case DFF_msofbtSolverContainer:
3784 isBreak = !ProcessSolverContainer( rDffStrm, aHeader );
3785 break;
3786 case DFF_msofbtSpgrContainer:
3787 isBreak = !ProcessShGrContainer( rDffStrm, aHeader );
3788 break;
3789 default:
3790 isBreak = !aHeader.SeekToEndOfRecord( rDffStrm );
3793 // seek to end of drawing page container
3794 isBreak = !rDgHeader.SeekToEndOfRecord( rDffStrm );
3796 // #i12638# #i37900# connector rules
3797 XclImpSolverContainer& rSolverCont = GetConvData().maSolverCont;
3798 rSolverCont.UpdateConnectorRules();
3799 SolveSolver( rSolverCont );
3800 rSolverCont.RemoveConnectorRules();
3801 return !isBreak;
3804 bool XclImpDffConverter::ProcessShGrContainer( SvStream& rDffStrm, const DffRecordHeader& rShGrHeader )
3806 std::size_t nEndPos = rShGrHeader.GetRecEndFilePos();
3807 bool isBreak(false);
3808 while (!isBreak && rDffStrm.good() && rDffStrm.Tell() < nEndPos)
3810 DffRecordHeader aHeader;
3811 ReadDffRecordHeader( rDffStrm, aHeader );
3812 switch( aHeader.nRecType )
3814 case DFF_msofbtSpgrContainer:
3815 case DFF_msofbtSpContainer:
3816 isBreak = !ProcessShContainer( rDffStrm, aHeader );
3817 break;
3818 default:
3819 isBreak = !aHeader.SeekToEndOfRecord( rDffStrm );
3822 // seek to end of shape group container
3823 return rShGrHeader.SeekToEndOfRecord( rDffStrm ) && !isBreak;
3826 bool XclImpDffConverter::ProcessSolverContainer( SvStream& rDffStrm, const DffRecordHeader& rSolverHeader )
3828 // solver container wants to read the solver container header again
3829 rSolverHeader.SeekToBegOfRecord( rDffStrm );
3830 // read the entire solver container
3831 ReadSvxMSDffSolverContainer( rDffStrm, GetConvData().maSolverCont );
3832 // seek to end of solver container
3833 return rSolverHeader.SeekToEndOfRecord( rDffStrm );
3836 bool XclImpDffConverter::ProcessShContainer( SvStream& rDffStrm, const DffRecordHeader& rShHeader )
3838 rShHeader.SeekToBegOfRecord( rDffStrm );
3839 tools::Rectangle aDummy;
3840 XclImpDrawObjClientData aDrawObjClientData;
3841 /* The call to ImportObj() creates and returns a new SdrObject for the
3842 processed shape. We take ownership of the returned object here. If the
3843 shape is a group object, all embedded objects are created recursively,
3844 and the returned group object contains them all. ImportObj() calls the
3845 virtual functions ProcessClientAnchor2() and ProcessObj() and writes
3846 the pointer to the related draw object data (OBJ record) into aDrawObjClientData. */
3847 SdrObjectUniquePtr xSdrObj( ImportObj( rDffStrm, aDrawObjClientData, aDummy, aDummy, /*nCalledByGroup*/0, /*pShapeId*/nullptr ) );
3848 if (aDrawObjClientData.m_pTopLevelObj && xSdrObj )
3849 InsertSdrObject( GetConvData().mrSdrPage, *aDrawObjClientData.m_pTopLevelObj, xSdrObj.release() );
3850 return rShHeader.SeekToEndOfRecord( rDffStrm );
3853 void XclImpDffConverter::InsertSdrObject( SdrObjList& rObjList, const XclImpDrawObjBase& rDrawObj, SdrObject* pSdrObj )
3855 XclImpDffConvData& rConvData = GetConvData();
3856 /* Take ownership of the passed object. If insertion fails (e.g. rDrawObj
3857 states to skip insertion), the object is automatically deleted. */
3858 SdrObjectUniquePtr xSdrObj( pSdrObj );
3859 if( xSdrObj && rDrawObj.IsInsertSdrObj() )
3861 rObjList.NbcInsertObject( xSdrObj.release() );
3862 // callback to drawing manager for e.g. tracking of used sheet area
3863 rConvData.mrDrawing.OnObjectInserted( rDrawObj );
3864 // callback to drawing object for post processing (use pSdrObj, xSdrObj already released)
3865 rDrawObj.PostProcessSdrObject( *this, *pSdrObj );
3867 /* SdrObject still here? Insertion failed, remove data from shape ID map.
3868 The SdrObject will be destructed then. */
3869 if( xSdrObj )
3870 rConvData.maSolverCont.RemoveSdrObjectInfo( *xSdrObj );
3873 void XclImpDffConverter::InitControlForm()
3875 XclImpDffConvData& rConvData = GetConvData();
3876 if( rConvData.mbHasCtrlForm )
3877 return;
3879 rConvData.mbHasCtrlForm = true;
3880 if( SupportsOleObjects() ) try
3882 Reference< XFormsSupplier > xFormsSupplier( rConvData.mrSdrPage.getUnoPage(), UNO_QUERY_THROW );
3883 Reference< XNameContainer > xFormsNC( xFormsSupplier->getForms(), UNO_SET_THROW );
3884 // find or create the Standard form used to insert the imported controls
3885 if( xFormsNC->hasByName( gaStdFormName ) )
3887 xFormsNC->getByName( gaStdFormName ) >>= rConvData.mxCtrlForm;
3889 else if( SfxObjectShell* pDocShell = GetDocShell() )
3891 rConvData.mxCtrlForm.set( ScfApiHelper::CreateInstance( pDocShell, "com.sun.star.form.component.Form" ), UNO_QUERY_THROW );
3892 xFormsNC->insertByName( gaStdFormName, Any( rConvData.mxCtrlForm ) );
3895 catch( const Exception& )
3900 // Drawing manager ============================================================
3902 XclImpDrawing::XclImpDrawing( const XclImpRoot& rRoot, bool bOleObjects ) :
3903 XclImpRoot( rRoot ),
3904 mbOleObjs( bOleObjects )
3908 XclImpDrawing::~XclImpDrawing()
3912 Graphic XclImpDrawing::ReadImgData( const XclImpRoot& rRoot, XclImpStream& rStrm )
3914 Graphic aGraphic;
3915 sal_uInt16 nFormat = rStrm.ReaduInt16();
3916 rStrm.Ignore( 2 );//nEnv
3917 sal_uInt32 nDataSize = rStrm.ReaduInt32();
3918 if( nDataSize <= rStrm.GetRecLeft() )
3920 switch( nFormat )
3922 case EXC_IMGDATA_WMF: ReadWmf( aGraphic, rStrm ); break;
3923 case EXC_IMGDATA_BMP: ReadBmp( aGraphic, rRoot, rStrm ); break;
3924 default: OSL_FAIL( "XclImpDrawing::ReadImgData - unknown image format" );
3927 return aGraphic;
3930 void XclImpDrawing::ReadObj( XclImpStream& rStrm )
3932 XclImpDrawObjRef xDrawObj;
3934 /* #i61786# In BIFF8 streams, OBJ records may occur without MSODRAWING
3935 records. In this case, the OBJ records are in BIFF5 format. Do a sanity
3936 check here that there is no DFF data loaded before. */
3937 OSL_ENSURE( maDffStrm.Tell() == 0, "XclImpDrawing::ReadObj - unexpected DFF stream data, OBJ will be ignored" );
3938 if( maDffStrm.Tell() == 0 ) switch( GetBiff() )
3940 case EXC_BIFF3:
3941 xDrawObj = XclImpDrawObjBase::ReadObj3( GetRoot(), rStrm );
3942 break;
3943 case EXC_BIFF4:
3944 xDrawObj = XclImpDrawObjBase::ReadObj4( GetRoot(), rStrm );
3945 break;
3946 case EXC_BIFF5:
3947 case EXC_BIFF8:
3948 xDrawObj = XclImpDrawObjBase::ReadObj5( GetRoot(), rStrm );
3949 break;
3950 default:
3951 DBG_ERROR_BIFF();
3954 if( xDrawObj )
3956 // insert into maRawObjs or into the last open group object
3957 maRawObjs.InsertGrouped( xDrawObj );
3958 // to be able to find objects by ID
3959 maObjMapId[ xDrawObj->GetObjId() ] = xDrawObj;
3963 void XclImpDrawing::ReadMsoDrawing( XclImpStream& rStrm )
3965 OSL_ENSURE_BIFF( GetBiff() == EXC_BIFF8 );
3966 // disable internal CONTINUE handling
3967 rStrm.ResetRecord( false );
3968 // read leading MSODRAWING record
3969 ReadDffRecord( rStrm );
3971 // read following drawing records, but do not start following unrelated record
3972 bool bLoop = true;
3973 while( bLoop ) switch( rStrm.GetNextRecId() )
3975 case EXC_ID_MSODRAWING:
3976 case EXC_ID_MSODRAWINGSEL:
3977 case EXC_ID_CONT:
3978 rStrm.StartNextRecord();
3979 ReadDffRecord( rStrm );
3980 break;
3981 case EXC_ID_OBJ:
3982 rStrm.StartNextRecord();
3983 ReadObj8( rStrm );
3984 break;
3985 case EXC_ID_TXO:
3986 rStrm.StartNextRecord();
3987 ReadTxo( rStrm );
3988 break;
3989 default:
3990 bLoop = false;
3993 // re-enable internal CONTINUE handling
3994 rStrm.ResetRecord( true );
3997 XclImpDrawObjRef XclImpDrawing::FindDrawObj( const DffRecordHeader& rHeader ) const
3999 /* maObjMap stores objects by position of the client data (OBJ record) in
4000 the DFF stream, which is always behind shape start position of the
4001 passed header. The function upper_bound() finds the first element in
4002 the map whose key is greater than the start position of the header. Its
4003 end position is used to test whether the found object is really related
4004 to the shape. */
4005 XclImpDrawObjRef xDrawObj;
4006 XclImpObjMap::const_iterator aIt = maObjMap.upper_bound( rHeader.GetRecBegFilePos() );
4007 if( (aIt != maObjMap.end()) && (aIt->first <= rHeader.GetRecEndFilePos()) )
4008 xDrawObj = aIt->second;
4009 return xDrawObj;
4012 XclImpDrawObjRef XclImpDrawing::FindDrawObj( sal_uInt16 nObjId ) const
4014 XclImpDrawObjRef xDrawObj;
4015 XclImpObjMapById::const_iterator aIt = maObjMapId.find( nObjId );
4016 if( aIt != maObjMapId.end() )
4017 xDrawObj = aIt->second;
4018 return xDrawObj;
4021 const XclImpObjTextData* XclImpDrawing::FindTextData( const DffRecordHeader& rHeader ) const
4023 /* maTextMap stores textbox data by position of the client data (TXO
4024 record) in the DFF stream, which is always behind shape start position
4025 of the passed header. The function upper_bound() finds the first
4026 element in the map whose key is greater than the start position of the
4027 header. Its end position is used to test whether the found object is
4028 really related to the shape. */
4029 XclImpObjTextMap::const_iterator aIt = maTextMap.upper_bound( rHeader.GetRecBegFilePos() );
4030 if( (aIt != maTextMap.end()) && (aIt->first <= rHeader.GetRecEndFilePos()) )
4031 return aIt->second.get();
4032 return nullptr;
4035 void XclImpDrawing::SetSkipObj( sal_uInt16 nObjId )
4037 maSkipObjs.push_back( nObjId );
4040 std::size_t XclImpDrawing::GetProgressSize() const
4042 return std::accumulate(maObjMap.begin(), maObjMap.end(), maRawObjs.GetProgressSize(),
4043 [](const std::size_t& rSum, const XclImpObjMap::value_type& rEntry) { return rSum + rEntry.second->GetProgressSize(); });
4046 void XclImpDrawing::ImplConvertObjects( XclImpDffConverter& rDffConv, SdrModel& rSdrModel, SdrPage& rSdrPage )
4048 //rhbz#636521, disable undo during conversion. faster, smaller and stops
4049 //temp objects being inserted into the undo list
4050 bool bOrigUndoStatus = rSdrModel.IsUndoEnabled();
4051 rSdrModel.EnableUndo(false);
4052 // register this drawing manager at the passed (global) DFF manager
4053 rDffConv.InitializeDrawing( *this, rSdrModel, rSdrPage );
4054 // process list of objects to be skipped
4055 for( const auto& rSkipObj : maSkipObjs )
4056 if( XclImpDrawObjBase* pDrawObj = FindDrawObj( rSkipObj ).get() )
4057 pDrawObj->SetProcessSdrObj( false );
4058 // process drawing objects without DFF data
4059 rDffConv.ProcessDrawing( maRawObjs );
4060 // process all objects in the DFF stream
4061 rDffConv.ProcessDrawing( maDffStrm );
4062 // unregister this drawing manager at the passed (global) DFF manager
4063 rDffConv.FinalizeDrawing();
4064 rSdrModel.EnableUndo(bOrigUndoStatus);
4067 // protected ------------------------------------------------------------------
4069 void XclImpDrawing::AppendRawObject( const XclImpDrawObjRef& rxDrawObj )
4071 OSL_ENSURE( rxDrawObj, "XclImpDrawing::AppendRawObject - unexpected empty reference" );
4072 maRawObjs.push_back( rxDrawObj );
4075 // private --------------------------------------------------------------------
4077 void XclImpDrawing::ReadWmf( Graphic& rGraphic, XclImpStream& rStrm ) // static helper
4079 // extract graphic data from IMGDATA and following CONTINUE records
4080 rStrm.Ignore( 8 );
4081 SvMemoryStream aMemStrm;
4082 rStrm.CopyToStream( aMemStrm, rStrm.GetRecLeft() );
4083 aMemStrm.Seek( STREAM_SEEK_TO_BEGIN );
4084 // import the graphic from memory stream
4085 GDIMetaFile aGDIMetaFile;
4086 if( ::ReadWindowMetafile( aMemStrm, aGDIMetaFile ) )
4087 rGraphic = aGDIMetaFile;
4090 void XclImpDrawing::ReadBmp( Graphic& rGraphic, const XclImpRoot& rRoot, XclImpStream& rStrm ) // static helper
4092 // extract graphic data from IMGDATA and following CONTINUE records
4093 SvMemoryStream aMemStrm;
4095 /* Excel 3 and 4 seem to write broken BMP data. Usually they write a
4096 DIBCOREHEADER (12 bytes) containing width, height, planes = 1, and
4097 pixel depth = 32 bit. After that, 3 unused bytes are added before the
4098 actual pixel data. This does even confuse Excel 5 and later, which
4099 cannot read the image data correctly. */
4100 if( rRoot.GetBiff() <= EXC_BIFF4 )
4102 rStrm.PushPosition();
4103 sal_uInt32 nHdrSize;
4104 sal_uInt16 nWidth, nHeight, nPlanes, nDepth;
4105 nHdrSize = rStrm.ReaduInt32();
4106 nWidth = rStrm.ReaduInt16();
4107 nHeight = rStrm.ReaduInt16();
4108 nPlanes = rStrm.ReaduInt16();
4109 nDepth = rStrm.ReaduInt16();
4110 if( (nHdrSize == 12) && (nPlanes == 1) && (nDepth == 32) )
4112 rStrm.Ignore( 3 );
4113 aMemStrm.SetEndian( SvStreamEndian::LITTLE );
4114 aMemStrm.WriteUInt32( nHdrSize ).WriteUInt16( nWidth ).WriteUInt16( nHeight ).WriteUInt16( nPlanes ).WriteUInt16( nDepth );
4115 rStrm.CopyToStream( aMemStrm, rStrm.GetRecLeft() );
4117 rStrm.PopPosition();
4120 // no special handling above -> just copy the remaining record data
4121 if( aMemStrm.Tell() == 0 )
4122 rStrm.CopyToStream( aMemStrm, rStrm.GetRecLeft() );
4124 // import the graphic from memory stream
4125 aMemStrm.Seek( STREAM_SEEK_TO_BEGIN );
4126 Bitmap aBitmap;
4127 if( ReadDIB(aBitmap, aMemStrm, false) ) // read DIB without file header
4128 rGraphic = aBitmap;
4131 void XclImpDrawing::ReadDffRecord( XclImpStream& rStrm )
4133 maDffStrm.Seek( STREAM_SEEK_TO_END );
4134 rStrm.CopyRecordToStream( maDffStrm );
4137 void XclImpDrawing::ReadObj8( XclImpStream& rStrm )
4139 XclImpDrawObjRef xDrawObj = XclImpDrawObjBase::ReadObj8( GetRoot(), rStrm );
4140 // store the new object in the internal containers
4141 maObjMap[ maDffStrm.Tell() ] = xDrawObj;
4142 maObjMapId[ xDrawObj->GetObjId() ] = xDrawObj;
4145 void XclImpDrawing::ReadTxo( XclImpStream& rStrm )
4147 XclImpObjTextRef xTextData( new XclImpObjTextData );
4148 maTextMap[ maDffStrm.Tell() ] = xTextData;
4150 // 1) read the TXO record
4151 xTextData->maData.ReadTxo8( rStrm );
4153 // 2) first CONTINUE with string
4154 xTextData->mxString.reset();
4155 bool bValid = true;
4156 if( xTextData->maData.mnTextLen > 0 )
4158 bValid = (rStrm.GetNextRecId() == EXC_ID_CONT) && rStrm.StartNextRecord();
4159 OSL_ENSURE( bValid, "XclImpDrawing::ReadTxo - missing CONTINUE record" );
4160 if( bValid )
4161 xTextData->mxString.reset( new XclImpString( rStrm.ReadUniString( xTextData->maData.mnTextLen ) ) );
4164 // 3) second CONTINUE with formatting runs
4165 if( xTextData->maData.mnFormatSize > 0 )
4167 bValid = (rStrm.GetNextRecId() == EXC_ID_CONT) && rStrm.StartNextRecord();
4168 OSL_ENSURE( bValid, "XclImpDrawing::ReadTxo - missing CONTINUE record" );
4169 if( bValid )
4170 xTextData->ReadFormats( rStrm );
4174 XclImpSheetDrawing::XclImpSheetDrawing( const XclImpRoot& rRoot, SCTAB nScTab ) :
4175 XclImpDrawing( rRoot, true ),
4176 maScUsedArea( ScAddress::INITIALIZE_INVALID )
4178 maScUsedArea.aStart.SetTab( nScTab );
4179 maScUsedArea.aEnd.SetTab( nScTab );
4182 void XclImpSheetDrawing::ReadNote( XclImpStream& rStrm )
4184 switch( GetBiff() )
4186 case EXC_BIFF2:
4187 case EXC_BIFF3:
4188 case EXC_BIFF4:
4189 case EXC_BIFF5:
4190 ReadNote3( rStrm );
4191 break;
4192 case EXC_BIFF8:
4193 ReadNote8( rStrm );
4194 break;
4195 default:
4196 DBG_ERROR_BIFF();
4200 void XclImpSheetDrawing::ReadTabChart( XclImpStream& rStrm )
4202 OSL_ENSURE_BIFF( GetBiff() >= EXC_BIFF5 );
4203 std::shared_ptr< XclImpChartObj > xChartObj( new XclImpChartObj( GetRoot(), true ) );
4204 xChartObj->ReadChartSubStream( rStrm );
4205 // insert the chart as raw object without connected DFF data
4206 AppendRawObject( xChartObj );
4209 void XclImpSheetDrawing::ConvertObjects( XclImpDffConverter& rDffConv )
4211 if( SdrModel* pSdrModel = GetDoc().GetDrawLayer() )
4212 if( SdrPage* pSdrPage = GetSdrPage( maScUsedArea.aStart.Tab() ) )
4213 ImplConvertObjects( rDffConv, *pSdrModel, *pSdrPage );
4216 tools::Rectangle XclImpSheetDrawing::CalcAnchorRect( const XclObjAnchor& rAnchor, bool /*bDffAnchor*/ ) const
4218 return rAnchor.GetRect( GetRoot(), maScUsedArea.aStart.Tab(), MapUnit::Map100thMM );
4221 void XclImpSheetDrawing::OnObjectInserted( const XclImpDrawObjBase& rDrawObj )
4223 ScRange aScObjArea = rDrawObj.GetUsedArea( maScUsedArea.aStart.Tab() );
4224 if( aScObjArea.IsValid() )
4225 maScUsedArea.ExtendTo( aScObjArea );
4228 // private --------------------------------------------------------------------
4230 void XclImpSheetDrawing::ReadNote3( XclImpStream& rStrm )
4232 XclAddress aXclPos;
4233 sal_uInt16 nTotalLen;
4234 rStrm >> aXclPos;
4235 nTotalLen = rStrm.ReaduInt16();
4237 ScAddress aScNotePos( ScAddress::UNINITIALIZED );
4238 if( GetAddressConverter().ConvertAddress( aScNotePos, aXclPos, maScUsedArea.aStart.Tab(), true ) )
4240 sal_uInt16 nPartLen = ::std::min( nTotalLen, static_cast< sal_uInt16 >( rStrm.GetRecLeft() ) );
4241 OUStringBuffer aNoteText = rStrm.ReadRawByteString( nPartLen );
4242 nTotalLen = nTotalLen - nPartLen;
4243 while( (nTotalLen > 0) && (rStrm.GetNextRecId() == EXC_ID_NOTE) && rStrm.StartNextRecord() )
4245 rStrm >> aXclPos;
4246 nPartLen = rStrm.ReaduInt16();
4247 OSL_ENSURE( aXclPos.mnRow == 0xFFFF, "XclImpObjectManager::ReadNote3 - missing continuation NOTE record" );
4248 if( aXclPos.mnRow == 0xFFFF )
4250 OSL_ENSURE( nPartLen <= nTotalLen, "XclImpObjectManager::ReadNote3 - string too long" );
4251 aNoteText.append(rStrm.ReadRawByteString( nPartLen ));
4252 nTotalLen = nTotalLen - ::std::min( nTotalLen, nPartLen );
4254 else
4256 // seems to be a new note, record already started -> load the note
4257 rStrm.Seek( EXC_REC_SEEK_TO_BEGIN );
4258 ReadNote( rStrm );
4259 nTotalLen = 0;
4262 ScNoteUtil::CreateNoteFromString( GetDoc(), aScNotePos, aNoteText.makeStringAndClear(), false, false );
4266 void XclImpSheetDrawing::ReadNote8( XclImpStream& rStrm )
4268 XclAddress aXclPos;
4269 sal_uInt16 nFlags, nObjId;
4270 rStrm >> aXclPos;
4271 nFlags = rStrm.ReaduInt16();
4272 nObjId = rStrm.ReaduInt16();
4274 ScAddress aScNotePos( ScAddress::UNINITIALIZED );
4275 if( GetAddressConverter().ConvertAddress( aScNotePos, aXclPos, maScUsedArea.aStart.Tab(), true ) )
4276 if( nObjId != EXC_OBJ_INVALID_ID )
4277 if( XclImpNoteObj* pNoteObj = dynamic_cast< XclImpNoteObj* >( FindDrawObj( nObjId ).get() ) )
4278 pNoteObj->SetNoteData( aScNotePos, nFlags );
4281 // The object manager =========================================================
4283 XclImpObjectManager::XclImpObjectManager( const XclImpRoot& rRoot ) :
4284 XclImpRoot( rRoot )
4286 maDefObjNames[ EXC_OBJTYPE_GROUP ] = "Group";
4287 maDefObjNames[ EXC_OBJTYPE_LINE ] = ScResId( STR_SHAPE_LINE );
4288 maDefObjNames[ EXC_OBJTYPE_RECTANGLE ] = ScResId( STR_SHAPE_RECTANGLE );
4289 maDefObjNames[ EXC_OBJTYPE_OVAL ] = ScResId( STR_SHAPE_OVAL );
4290 maDefObjNames[ EXC_OBJTYPE_ARC ] = "Arc";
4291 maDefObjNames[ EXC_OBJTYPE_CHART ] = "Chart";
4292 maDefObjNames[ EXC_OBJTYPE_TEXT ] = "Text";
4293 maDefObjNames[ EXC_OBJTYPE_BUTTON ] = ScResId( STR_FORM_BUTTON );
4294 maDefObjNames[ EXC_OBJTYPE_PICTURE ] = "Picture";
4295 maDefObjNames[ EXC_OBJTYPE_POLYGON ] = "Freeform";
4296 maDefObjNames[ EXC_OBJTYPE_CHECKBOX ] = ScResId( STR_FORM_CHECKBOX );
4297 maDefObjNames[ EXC_OBJTYPE_OPTIONBUTTON ] = ScResId( STR_FORM_OPTIONBUTTON );
4298 maDefObjNames[ EXC_OBJTYPE_EDIT ] = "Edit Box";
4299 maDefObjNames[ EXC_OBJTYPE_LABEL ] = ScResId( STR_FORM_LABEL );
4300 maDefObjNames[ EXC_OBJTYPE_DIALOG ] = "Dialog Frame";
4301 maDefObjNames[ EXC_OBJTYPE_SPIN ] = ScResId( STR_FORM_SPINNER );
4302 maDefObjNames[ EXC_OBJTYPE_SCROLLBAR ] = ScResId( STR_FORM_SCROLLBAR );
4303 maDefObjNames[ EXC_OBJTYPE_LISTBOX ] = ScResId( STR_FORM_LISTBOX );
4304 maDefObjNames[ EXC_OBJTYPE_GROUPBOX ] = ScResId( STR_FORM_GROUPBOX );
4305 maDefObjNames[ EXC_OBJTYPE_DROPDOWN ] = ScResId( STR_FORM_DROPDOWN );
4306 maDefObjNames[ EXC_OBJTYPE_NOTE ] = "Comment";
4307 maDefObjNames[ EXC_OBJTYPE_DRAWING ] = ScResId( STR_SHAPE_AUTOSHAPE );
4310 XclImpObjectManager::~XclImpObjectManager()
4314 void XclImpObjectManager::ReadMsoDrawingGroup( XclImpStream& rStrm )
4316 OSL_ENSURE_BIFF( GetBiff() == EXC_BIFF8 );
4317 // Excel continues this record with MSODRAWINGGROUP and CONTINUE records, hmm.
4318 rStrm.ResetRecord( true, EXC_ID_MSODRAWINGGROUP );
4319 maDggStrm.Seek( STREAM_SEEK_TO_END );
4320 rStrm.CopyRecordToStream( maDggStrm );
4323 XclImpSheetDrawing& XclImpObjectManager::GetSheetDrawing( SCTAB nScTab )
4325 XclImpSheetDrawingRef& rxDrawing = maSheetDrawings[ nScTab ];
4326 if( !rxDrawing )
4327 rxDrawing.reset( new XclImpSheetDrawing( GetRoot(), nScTab ) );
4328 return *rxDrawing;
4331 void XclImpObjectManager::ConvertObjects()
4333 // do nothing if the document does not contain a drawing layer
4334 if( !GetDoc().GetDrawLayer() )
4335 return;
4337 // get total progress bar size for all sheet drawing managers
4338 std::size_t nProgressSize = std::accumulate(maSheetDrawings.begin(), maSheetDrawings.end(), std::size_t(0),
4339 [](const std::size_t& rSum, const XclImpSheetDrawingMap::value_type& rEntry) { return rSum + rEntry.second->GetProgressSize(); });
4340 // nothing to do if progress bar is zero (no objects present)
4341 if( nProgressSize == 0 )
4342 return;
4344 XclImpDffConverter aDffConv( GetRoot(), maDggStrm );
4345 aDffConv.StartProgressBar( nProgressSize );
4346 for( auto& rEntry : maSheetDrawings )
4347 rEntry.second->ConvertObjects( aDffConv );
4349 // #i112436# don't call ScChartListenerCollection::SetDirty here,
4350 // instead use InterpretDirtyCells in ScDocument::CalcAfterLoad.
4353 OUString XclImpObjectManager::GetDefaultObjName( const XclImpDrawObjBase& rDrawObj ) const
4355 OUStringBuffer aDefName;
4356 DefObjNameMap::const_iterator aIt = maDefObjNames.find( rDrawObj.GetObjType() );
4357 if( aIt != maDefObjNames.end() )
4358 aDefName.append(aIt->second);
4359 return aDefName.append(' ').append(static_cast<sal_Int32>(rDrawObj.GetObjId())).makeStringAndClear();
4362 ScRange XclImpObjectManager::GetUsedArea( SCTAB nScTab ) const
4364 XclImpSheetDrawingMap::const_iterator aIt = maSheetDrawings.find( nScTab );
4365 if( aIt != maSheetDrawings.end() )
4366 return aIt->second->GetUsedArea();
4367 return ScRange( ScAddress::INITIALIZE_INVALID );
4370 // DFF property set helper ====================================================
4372 XclImpDffPropSet::XclImpDffPropSet( const XclImpRoot& rRoot ) :
4373 XclImpRoot( rRoot ),
4374 maDffConv( rRoot, maDummyStrm )
4378 void XclImpDffPropSet::Read( XclImpStream& rStrm )
4380 sal_uInt32 nPropSetSize;
4382 rStrm.PushPosition();
4383 rStrm.Ignore( 4 );
4384 nPropSetSize = rStrm.ReaduInt32();
4385 rStrm.PopPosition();
4387 mxMemStrm.reset( new SvMemoryStream );
4388 rStrm.CopyToStream( *mxMemStrm, 8 + nPropSetSize );
4389 mxMemStrm->Seek( STREAM_SEEK_TO_BEGIN );
4390 maDffConv.ReadPropSet( *mxMemStrm, nullptr );
4393 sal_uInt32 XclImpDffPropSet::GetPropertyValue( sal_uInt16 nPropId ) const
4395 return maDffConv.GetPropertyValue( nPropId, 0 );
4398 void XclImpDffPropSet::FillToItemSet( SfxItemSet& rItemSet ) const
4400 if( mxMemStrm.get() )
4401 maDffConv.ApplyAttributes( *mxMemStrm, rItemSet );
4404 XclImpStream& operator>>( XclImpStream& rStrm, XclImpDffPropSet& rPropSet )
4406 rPropSet.Read( rStrm );
4407 return rStrm;
4410 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */