use insert function instead of for loop
[LibreOffice.git] / sc / source / filter / excel / xiescher.cxx
blob81edde0ac3cbd0b5a0bed492feb322e5899b3cd0
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 <officecfg/Office/Common.hxx>
46 #include <unotools/moduleoptions.hxx>
47 #include <comphelper/configuration.hxx>
48 #include <vcl/dibtools.hxx>
49 #include <vcl/gdimtf.hxx>
50 #include <vcl/outdev.hxx>
51 #include <vcl/wmf.hxx>
52 #include <comphelper/classids.hxx>
53 #include <comphelper/documentinfo.hxx>
54 #include <o3tl/safeint.hxx>
55 #include <toolkit/helper/vclunohelper.hxx>
56 #include <basegfx/point/b2dpoint.hxx>
57 #include <basegfx/polygon/b2dpolygon.hxx>
58 #include <sal/log.hxx>
60 #include <svx/svdopath.hxx>
61 #include <svx/svdocirc.hxx>
62 #include <svx/svdoedge.hxx>
63 #include <svx/svdogrp.hxx>
64 #include <svx/svdoashp.hxx>
65 #include <svx/svdograf.hxx>
66 #include <svx/svdoole2.hxx>
67 #include <svx/svdouno.hxx>
68 #include <svx/svdpage.hxx>
69 #include <editeng/editobj.hxx>
70 #include <editeng/outliner.hxx>
71 #include <editeng/outlobj.hxx>
72 #include <svx/svditer.hxx>
73 #include <editeng/writingmodeitem.hxx>
74 #include <svx/xlnclit.hxx>
75 #include <svx/xlndsit.hxx>
76 #include <svx/xlnedcit.hxx>
77 #include <svx/xlnedit.hxx>
78 #include <svx/xlnedwit.hxx>
79 #include <svx/xlnstcit.hxx>
80 #include <svx/xlnstit.hxx>
81 #include <svx/xlnstwit.hxx>
82 #include <svx/xlnwtit.hxx>
83 #include <svx/sdasitm.hxx>
84 #include <svx/sdshcitm.hxx>
85 #include <svx/sdshitm.hxx>
86 #include <svx/sdsxyitm.hxx>
87 #include <svx/sdtagitm.hxx>
88 #include <svx/sdtditm.hxx>
90 #include <editeng/eeitem.hxx>
91 #include <svx/xflclit.hxx>
92 #include <sal/macros.h>
93 #include <editeng/adjustitem.hxx>
94 #include <svx/xfillit0.hxx>
95 #include <svx/xlineit0.hxx>
96 #include <svx/xlinjoit.hxx>
97 #include <svx/xlntrit.hxx>
98 #include <svx/xbtmpit.hxx>
99 #include <svx/xbitmap.hxx>
100 #include <svtools/embedhlp.hxx>
101 #include <sot/storage.hxx>
103 #include <document.hxx>
104 #include <drwlayer.hxx>
105 #include <docsh.hxx>
106 #include <userdat.hxx>
107 #include <unonames.hxx>
108 #include <convuno.hxx>
109 #include <postit.hxx>
110 #include <globstr.hrc>
111 #include <scresid.hxx>
113 #include <fprogressbar.hxx>
114 #include <xltracer.hxx>
115 #include <xistream.hxx>
116 #include <xihelper.hxx>
117 #include <xiformula.hxx>
118 #include <xilink.hxx>
119 #include <xistyle.hxx>
120 #include <xipage.hxx>
121 #include <xichart.hxx>
122 #include <xicontent.hxx>
123 #include <scextopt.hxx>
125 #include <namebuff.hxx>
126 #include <sfx2/docfile.hxx>
127 #include <memory>
128 #include <numeric>
129 #include <string_view>
130 #include <utility>
132 using namespace com::sun::star;
133 using ::com::sun::star::uno::Any;
134 using ::com::sun::star::beans::XPropertySet;
135 using ::com::sun::star::uno::Exception;
136 using ::com::sun::star::uno::Reference;
137 using ::com::sun::star::uno::Sequence;
138 using ::com::sun::star::uno::UNO_QUERY;
139 using ::com::sun::star::uno::UNO_QUERY_THROW;
140 using ::com::sun::star::uno::UNO_SET_THROW;
141 using ::com::sun::star::beans::NamedValue;
142 using ::com::sun::star::container::XIndexContainer;
143 using ::com::sun::star::container::XNameContainer;
144 using ::com::sun::star::frame::XModel;
145 using ::com::sun::star::awt::XControlModel;
146 using ::com::sun::star::embed::XEmbeddedObject;
147 using ::com::sun::star::embed::XEmbedPersist;
148 using ::com::sun::star::drawing::XControlShape;
149 using ::com::sun::star::drawing::XShape;
150 using ::com::sun::star::form::XFormComponent;
151 using ::com::sun::star::form::XFormsSupplier;
152 using ::com::sun::star::form::binding::XBindableValue;
153 using ::com::sun::star::form::binding::XValueBinding;
154 using ::com::sun::star::form::binding::XListEntrySink;
155 using ::com::sun::star::form::binding::XListEntrySource;
156 using ::com::sun::star::script::ScriptEventDescriptor;
157 using ::com::sun::star::script::XEventAttacherManager;
158 using ::com::sun::star::table::CellAddress;
159 using ::com::sun::star::table::CellRangeAddress;
161 // Drawing objects ============================================================
163 XclImpDrawObjBase::XclImpDrawObjBase( const XclImpRoot& rRoot ) :
164 XclImpRoot( rRoot ),
165 mnObjId( EXC_OBJ_INVALID_ID ),
166 mnTab( 0 ),
167 mnObjType( EXC_OBJTYPE_UNKNOWN ),
168 mnDffShapeId( 0 ),
169 mnDffFlags( ShapeFlag::NONE ),
170 mbHasAnchor( false ),
171 mbHidden( false ),
172 mbVisible( true ),
173 mbPrintable( true ),
174 mbAreaObj( false ),
175 mbAutoMargin( true ),
176 mbSimpleMacro( true ),
177 mbProcessSdr( true ),
178 mbInsertSdr( true ),
179 mbCustomDff( false ),
180 mbNotifyMacroEventRead( false )
184 XclImpDrawObjBase::~XclImpDrawObjBase()
188 XclImpDrawObjRef XclImpDrawObjBase::ReadObj3( const XclImpRoot& rRoot, XclImpStream& rStrm )
190 XclImpDrawObjRef xDrawObj;
192 if( rStrm.GetRecLeft() >= 30 )
194 sal_uInt16 nObjType;
195 rStrm.Ignore( 4 );
196 nObjType = rStrm.ReaduInt16();
197 switch( nObjType )
199 case EXC_OBJTYPE_GROUP: xDrawObj= std::make_shared<XclImpGroupObj>( rRoot ); break;
200 case EXC_OBJTYPE_LINE: xDrawObj= std::make_shared<XclImpLineObj>( rRoot ); break;
201 case EXC_OBJTYPE_RECTANGLE: xDrawObj= std::make_shared<XclImpRectObj>( rRoot ); break;
202 case EXC_OBJTYPE_OVAL: xDrawObj= std::make_shared<XclImpOvalObj>( rRoot ); break;
203 case EXC_OBJTYPE_ARC: xDrawObj= std::make_shared<XclImpArcObj>( rRoot ); break;
204 case EXC_OBJTYPE_CHART: xDrawObj= std::make_shared<XclImpChartObj>( rRoot ); break;
205 case EXC_OBJTYPE_TEXT: xDrawObj= std::make_shared<XclImpTextObj>( rRoot ); break;
206 case EXC_OBJTYPE_BUTTON: xDrawObj= std::make_shared<XclImpButtonObj>( rRoot ); break;
207 case EXC_OBJTYPE_PICTURE: xDrawObj= std::make_shared<XclImpPictureObj>( rRoot ); break;
208 default:
209 SAL_WARN("sc.filter", "XclImpDrawObjBase::ReadObj3 - unknown object type 0x" << std::hex << nObjType );
210 rRoot.GetTracer().TraceUnsupportedObjects();
214 if (!xDrawObj)
216 xDrawObj = std::make_shared<XclImpPhObj>(rRoot);
219 xDrawObj->mnTab = rRoot.GetCurrScTab();
220 xDrawObj->ImplReadObj3( rStrm );
221 return xDrawObj;
224 XclImpDrawObjRef XclImpDrawObjBase::ReadObj4( const XclImpRoot& rRoot, XclImpStream& rStrm )
226 XclImpDrawObjRef xDrawObj;
228 if( rStrm.GetRecLeft() >= 30 )
230 sal_uInt16 nObjType;
231 rStrm.Ignore( 4 );
232 nObjType = rStrm.ReaduInt16();
233 switch( nObjType )
235 case EXC_OBJTYPE_GROUP: xDrawObj = std::make_shared<XclImpGroupObj>( rRoot ); break;
236 case EXC_OBJTYPE_LINE: xDrawObj = std::make_shared<XclImpLineObj>( rRoot ); break;
237 case EXC_OBJTYPE_RECTANGLE: xDrawObj = std::make_shared<XclImpRectObj>( rRoot ); break;
238 case EXC_OBJTYPE_OVAL: xDrawObj = std::make_shared<XclImpOvalObj>( rRoot ); break;
239 case EXC_OBJTYPE_ARC: xDrawObj = std::make_shared<XclImpArcObj>( rRoot ); break;
240 case EXC_OBJTYPE_CHART: xDrawObj = std::make_shared<XclImpChartObj>( rRoot ); break;
241 case EXC_OBJTYPE_TEXT: xDrawObj = std::make_shared<XclImpTextObj>( rRoot ); break;
242 case EXC_OBJTYPE_BUTTON: xDrawObj = std::make_shared<XclImpButtonObj>( rRoot ); break;
243 case EXC_OBJTYPE_PICTURE: xDrawObj = std::make_shared<XclImpPictureObj>( rRoot ); break;
244 case EXC_OBJTYPE_POLYGON: xDrawObj = std::make_shared<XclImpPolygonObj>( rRoot ); break;
245 default:
246 SAL_WARN("sc.filter", "XclImpDrawObjBase::ReadObj4 - unknown object type 0x" << std::hex << nObjType );
247 rRoot.GetTracer().TraceUnsupportedObjects();
251 if (!xDrawObj)
253 xDrawObj = std::make_shared<XclImpPhObj>(rRoot);
256 xDrawObj->mnTab = rRoot.GetCurrScTab();
257 xDrawObj->ImplReadObj4( rStrm );
258 return xDrawObj;
261 XclImpDrawObjRef XclImpDrawObjBase::ReadObj5( const XclImpRoot& rRoot, XclImpStream& rStrm )
263 XclImpDrawObjRef xDrawObj;
265 if( rStrm.GetRecLeft() >= 34 )
267 sal_uInt16 nObjType(EXC_OBJTYPE_UNKNOWN);
268 rStrm.Ignore( 4 );
269 nObjType = rStrm.ReaduInt16();
270 switch( nObjType )
272 case EXC_OBJTYPE_GROUP: xDrawObj = std::make_shared<XclImpGroupObj>( rRoot ); break;
273 case EXC_OBJTYPE_LINE: xDrawObj = std::make_shared<XclImpLineObj>( rRoot ); break;
274 case EXC_OBJTYPE_RECTANGLE: xDrawObj = std::make_shared<XclImpRectObj>( rRoot ); break;
275 case EXC_OBJTYPE_OVAL: xDrawObj = std::make_shared<XclImpOvalObj>( rRoot ); break;
276 case EXC_OBJTYPE_ARC: xDrawObj = std::make_shared<XclImpArcObj>( rRoot ); break;
277 case EXC_OBJTYPE_CHART: xDrawObj = std::make_shared<XclImpChartObj>( rRoot ); break;
278 case EXC_OBJTYPE_TEXT: xDrawObj = std::make_shared<XclImpTextObj>( rRoot ); break;
279 case EXC_OBJTYPE_BUTTON: xDrawObj = std::make_shared<XclImpButtonObj>( rRoot ); break;
280 case EXC_OBJTYPE_PICTURE: xDrawObj = std::make_shared<XclImpPictureObj>( rRoot ); break;
281 case EXC_OBJTYPE_POLYGON: xDrawObj = std::make_shared<XclImpPolygonObj>( rRoot ); break;
282 case EXC_OBJTYPE_CHECKBOX: xDrawObj = std::make_shared<XclImpCheckBoxObj>( rRoot ); break;
283 case EXC_OBJTYPE_OPTIONBUTTON: xDrawObj = std::make_shared<XclImpOptionButtonObj>( rRoot ); break;
284 case EXC_OBJTYPE_EDIT: xDrawObj = std::make_shared<XclImpEditObj>( rRoot ); break;
285 case EXC_OBJTYPE_LABEL: xDrawObj = std::make_shared<XclImpLabelObj>( rRoot ); break;
286 case EXC_OBJTYPE_DIALOG: xDrawObj = std::make_shared<XclImpDialogObj>( rRoot ); break;
287 case EXC_OBJTYPE_SPIN: xDrawObj = std::make_shared<XclImpSpinButtonObj>( rRoot ); break;
288 case EXC_OBJTYPE_SCROLLBAR: xDrawObj = std::make_shared<XclImpScrollBarObj>( rRoot ); break;
289 case EXC_OBJTYPE_LISTBOX: xDrawObj = std::make_shared<XclImpListBoxObj>( rRoot ); break;
290 case EXC_OBJTYPE_GROUPBOX: xDrawObj = std::make_shared<XclImpGroupBoxObj>( rRoot ); break;
291 case EXC_OBJTYPE_DROPDOWN: xDrawObj = std::make_shared<XclImpDropDownObj>( rRoot ); break;
292 default:
293 SAL_WARN("sc.filter", "XclImpDrawObjBase::ReadObj5 - unknown object type 0x" << std::hex << nObjType );
294 rRoot.GetTracer().TraceUnsupportedObjects();
295 xDrawObj = std::make_shared<XclImpPhObj>( rRoot );
299 OSL_ENSURE(xDrawObj, "object import failed");
301 if (xDrawObj)
303 xDrawObj->mnTab = rRoot.GetCurrScTab();
304 xDrawObj->ImplReadObj5( rStrm );
306 return xDrawObj;
309 XclImpDrawObjRef XclImpDrawObjBase::ReadObj8( const XclImpRoot& rRoot, XclImpStream& rStrm )
311 XclImpDrawObjRef xDrawObj;
313 if( rStrm.GetRecLeft() >= 10 )
315 sal_uInt16 nSubRecId(0), nSubRecSize(0), nObjType(0);
316 nSubRecId = rStrm.ReaduInt16();
317 nSubRecSize = rStrm.ReaduInt16();
318 nObjType = rStrm.ReaduInt16();
319 OSL_ENSURE( nSubRecId == EXC_ID_OBJCMO, "XclImpDrawObjBase::ReadObj8 - OBJCMO subrecord expected" );
320 if( (nSubRecId == EXC_ID_OBJCMO) && (nSubRecSize >= 6) )
322 switch( nObjType )
324 // in BIFF8, all simple objects support text
325 case EXC_OBJTYPE_LINE:
326 case EXC_OBJTYPE_ARC:
327 xDrawObj = std::make_shared<XclImpTextObj>( rRoot );
328 // lines and arcs may be 2-dimensional
329 xDrawObj->SetAreaObj( false );
330 break;
332 // in BIFF8, all simple objects support text
333 case EXC_OBJTYPE_RECTANGLE:
334 case EXC_OBJTYPE_OVAL:
335 case EXC_OBJTYPE_POLYGON:
336 case EXC_OBJTYPE_DRAWING:
337 case EXC_OBJTYPE_TEXT:
338 xDrawObj = std::make_shared<XclImpTextObj>( rRoot );
339 break;
341 case EXC_OBJTYPE_GROUP: xDrawObj = std::make_shared<XclImpGroupObj>( rRoot ); break;
342 case EXC_OBJTYPE_CHART: xDrawObj = std::make_shared<XclImpChartObj>( rRoot ); break;
343 case EXC_OBJTYPE_BUTTON: xDrawObj = std::make_shared<XclImpButtonObj>( rRoot ); break;
344 case EXC_OBJTYPE_PICTURE: xDrawObj = std::make_shared<XclImpPictureObj>( rRoot ); break;
345 case EXC_OBJTYPE_CHECKBOX: xDrawObj = std::make_shared<XclImpCheckBoxObj>( rRoot ); break;
346 case EXC_OBJTYPE_OPTIONBUTTON: xDrawObj = std::make_shared<XclImpOptionButtonObj>( rRoot ); break;
347 case EXC_OBJTYPE_EDIT: xDrawObj = std::make_shared<XclImpEditObj>( rRoot ); break;
348 case EXC_OBJTYPE_LABEL: xDrawObj = std::make_shared<XclImpLabelObj>( rRoot ); break;
349 case EXC_OBJTYPE_DIALOG: xDrawObj = std::make_shared<XclImpDialogObj>( rRoot ); break;
350 case EXC_OBJTYPE_SPIN: xDrawObj = std::make_shared<XclImpSpinButtonObj>( rRoot ); break;
351 case EXC_OBJTYPE_SCROLLBAR: xDrawObj = std::make_shared<XclImpScrollBarObj>( rRoot ); break;
352 case EXC_OBJTYPE_LISTBOX: xDrawObj = std::make_shared<XclImpListBoxObj>( rRoot ); break;
353 case EXC_OBJTYPE_GROUPBOX: xDrawObj = std::make_shared<XclImpGroupBoxObj>( rRoot ); break;
354 case EXC_OBJTYPE_DROPDOWN: xDrawObj = std::make_shared<XclImpDropDownObj>( rRoot ); break;
355 case EXC_OBJTYPE_NOTE: xDrawObj = std::make_shared<XclImpNoteObj>( rRoot ); break;
357 default:
358 SAL_WARN("sc.filter", "XclImpDrawObjBase::ReadObj8 - unknown object type 0x" << std::hex << nObjType );
359 rRoot.GetTracer().TraceUnsupportedObjects();
364 if (!xDrawObj) //ensure placeholder for unknown or broken records
366 SAL_WARN( "sc.filter", "XclImpDrawObjBase::ReadObj8 import failed, substituting placeholder");
367 xDrawObj = std::make_shared<XclImpPhObj>( rRoot );
370 xDrawObj->mnTab = rRoot.GetCurrScTab();
371 xDrawObj->ImplReadObj8( rStrm );
372 return xDrawObj;
375 void XclImpDrawObjBase::SetAnchor( const XclObjAnchor& rAnchor )
377 maAnchor = rAnchor;
378 mbHasAnchor = true;
381 const tools::Rectangle& XclImpDrawObjBase::GetDffRect() const
383 return maDffRect;
386 void XclImpDrawObjBase::SetDffData(
387 const DffObjData& rDffObjData, const OUString& rObjName, const OUString& rHyperlink,
388 bool bVisible, bool bAutoMargin )
390 mnDffShapeId = rDffObjData.nShapeId;
391 mnDffFlags = rDffObjData.nSpFlags;
392 maObjName = rObjName;
393 maHyperlink = rHyperlink;
394 mbVisible = bVisible;
395 mbAutoMargin = bAutoMargin;
396 maDffRect = rDffObjData.aChildAnchor;
399 OUString XclImpDrawObjBase::GetObjName() const
401 /* #i51348# Always return a non-empty name. Create English
402 default names depending on the object type. This is not implemented as
403 virtual functions in derived classes, as class type and object type may
404 not match. */
405 return maObjName.isEmpty() ? GetObjectManager().GetDefaultObjName(*this) : maObjName;
408 const XclObjAnchor* XclImpDrawObjBase::GetAnchor() const
410 return mbHasAnchor ? &maAnchor : nullptr;
413 bool XclImpDrawObjBase::IsValidSize( const tools::Rectangle& rAnchorRect ) const
415 // XclObjAnchor rounds up the width, width of 3 is the result of an Excel width of 0
416 return mbAreaObj ?
417 ((rAnchorRect.GetWidth() > 3) && (rAnchorRect.GetHeight() > 1)) :
418 ((rAnchorRect.GetWidth() > 3) || (rAnchorRect.GetHeight() > 1));
421 ScRange XclImpDrawObjBase::GetUsedArea( SCTAB nScTab ) const
423 ScRange aScUsedArea( ScAddress::INITIALIZE_INVALID );
424 // #i44077# object inserted -> update used area for OLE object import
425 if( mbHasAnchor && GetAddressConverter().ConvertRange( aScUsedArea, maAnchor, nScTab, nScTab, false ) )
427 // reduce range, if object ends directly on borders between two columns or rows
428 if( (maAnchor.mnRX == 0) && (aScUsedArea.aStart.Col() < aScUsedArea.aEnd.Col()) )
429 aScUsedArea.aEnd.IncCol( -1 );
430 if( (maAnchor.mnBY == 0) && (aScUsedArea.aStart.Row() < aScUsedArea.aEnd.Row()) )
431 aScUsedArea.aEnd.IncRow( -1 );
433 return aScUsedArea;
436 std::size_t XclImpDrawObjBase::GetProgressSize() const
438 return DoGetProgressSize();
441 rtl::Reference<SdrObject> XclImpDrawObjBase::CreateSdrObject( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect, bool bIsDff ) const
443 rtl::Reference<SdrObject> xSdrObj;
444 if( bIsDff && !mbCustomDff )
446 rDffConv.Progress( GetProgressSize() );
448 else
450 xSdrObj = DoCreateSdrObj( rDffConv, rAnchorRect );
452 //added for exporting OCX control
453 /* mnObjType value set should be as below table:
454 0x0000 Group 0x0001 Line
455 0x0002 Rectangle 0x0003 Oval
456 0x0004 Arc 0x0005 Chart
457 0x0006 Text 0x0009 Polygon
458 +-----------------------------------------------------+
459 OCX ==>| 0x0008 Picture |
460 +-----------------------------------------------------+
461 | 0x0007 Button |
462 | 0x000B Checkbox 0x000C Radio button |
463 | 0x000D Edit box 0x000E Label |
464 TBX ==> | 0x000F Dialog box 0x0010 Spin control |
465 | 0x0011 Scrollbar 0x0012 List |
466 | 0x0013 Group box 0x0014 Dropdown list |
467 +-----------------------------------------------------+
468 0x0019 Note 0x001E OfficeArt object
470 if( xSdrObj && xSdrObj->IsUnoObj() &&
471 ( (mnObjType < 25 && mnObjType > 10) || mnObjType == 7 || mnObjType == 8 ) )
473 SdrUnoObj* pSdrUnoObj = dynamic_cast< SdrUnoObj* >( xSdrObj.get() );
474 if( pSdrUnoObj != nullptr )
476 const Reference< XControlModel >& xCtrlModel = pSdrUnoObj->GetUnoControlModel();
477 Reference< XPropertySet > xPropSet(xCtrlModel,UNO_QUERY);
478 static constexpr OUString sPropertyName(u"ControlTypeinMSO"_ustr);
480 enum { eCreateFromOffice = 0, eCreateFromMSTBXControl, eCreateFromMSOCXControl };
482 if( mnObjType == 7 || (mnObjType < 25 && mnObjType > 10) )//TBX
486 //Need summary type for export. Detail type(checkbox, button ...) has been contained by mnObjType
487 const sal_Int16 nTBXControlType = eCreateFromMSTBXControl ;
488 xPropSet->setPropertyValue(sPropertyName, Any(nTBXControlType));
490 catch(const Exception&)
492 SAL_WARN("sc.filter", "XclImpDrawObjBase::CreateSdrObject, this control can't be set the property ControlTypeinMSO!");
495 if( mnObjType == 8 )//OCX
497 //Need summary type for export
498 static constexpr OUStringLiteral sObjIdPropertyName(u"ObjIDinMSO");
499 const XclImpPictureObj* const pObj = dynamic_cast< const XclImpPictureObj* const >(this);
500 if( pObj != nullptr && pObj->IsOcxControl() )
504 const sal_Int16 nOCXControlType = eCreateFromMSOCXControl;
505 xPropSet->setPropertyValue(sPropertyName, Any(nOCXControlType));
506 //Detail type(checkbox, button ...)
507 xPropSet->setPropertyValue(sObjIdPropertyName, Any(sal_uInt16(mnObjId)));
509 catch(const Exception&)
511 SAL_WARN("sc.filter", "XclImpDrawObjBase::CreateSdrObject, this control can't be set the property ObjIDinMSO!");
519 return xSdrObj;
522 void XclImpDrawObjBase::NotifyMacroEventRead()
524 if (mbNotifyMacroEventRead)
525 return;
526 ScDocShell* pDocShell = GetDocShell();
527 if (!pDocShell)
528 return;
529 comphelper::DocumentInfo::notifyMacroEventRead(pDocShell->GetModel());
530 mbNotifyMacroEventRead = true;
533 void XclImpDrawObjBase::PreProcessSdrObject( XclImpDffConverter& rDffConv, SdrObject& rSdrObj )
535 // default: front layer, derived classes may have to set other layer in DoPreProcessSdrObj()
536 rSdrObj.NbcSetLayer( SC_LAYER_FRONT );
538 // set object name (GetObjName() will always return a non-empty name)
539 rSdrObj.SetName( GetObjName() );
541 // #i39167# full width for all objects regardless of horizontal alignment
542 rSdrObj.SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_BLOCK ) );
544 // automatic text margin
545 if( mbAutoMargin )
547 sal_Int32 nMargin = rDffConv.GetDefaultTextMargin();
548 rSdrObj.SetMergedItem( makeSdrTextLeftDistItem( nMargin ) );
549 rSdrObj.SetMergedItem( makeSdrTextRightDistItem( nMargin ) );
550 rSdrObj.SetMergedItem( makeSdrTextUpperDistItem( nMargin ) );
551 rSdrObj.SetMergedItem( makeSdrTextLowerDistItem( nMargin ) );
554 // macro and hyperlink
555 // removed oracle/sun check for mbSimpleMacro ( no idea what its for )
556 if (!maMacroName.isEmpty())
558 if( ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( &rSdrObj, true ) )
560 OUString sMacro = XclTools::GetSbMacroUrl(maMacroName, GetDocShell());
561 if (!sMacro.isEmpty())
562 NotifyMacroEventRead();
563 pInfo->SetMacro(sMacro);
566 if (!maHyperlink.isEmpty())
567 rSdrObj.setHyperlink(maHyperlink);
569 // call virtual function for object type specific processing
570 DoPreProcessSdrObj( rDffConv, rSdrObj );
573 void XclImpDrawObjBase::PostProcessSdrObject( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const
575 // call virtual function for object type specific processing
576 DoPostProcessSdrObj( rDffConv, rSdrObj );
579 // protected ------------------------------------------------------------------
581 void XclImpDrawObjBase::ReadName5( XclImpStream& rStrm, sal_uInt16 nNameLen )
583 maObjName.clear();
584 if( nNameLen > 0 )
586 // name length field is repeated before the name
587 maObjName = rStrm.ReadByteString( false );
588 // skip padding byte for word boundaries
589 if( rStrm.GetRecPos() & 1 ) rStrm.Ignore( 1 );
593 void XclImpDrawObjBase::ReadMacro3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
595 maMacroName.clear();
596 rStrm.Ignore( nMacroSize );
597 // skip padding byte for word boundaries, not contained in nMacroSize
598 if( rStrm.GetRecPos() & 1 ) rStrm.Ignore( 1 );
601 void XclImpDrawObjBase::ReadMacro4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
603 maMacroName.clear();
604 rStrm.Ignore( nMacroSize );
607 void XclImpDrawObjBase::ReadMacro5( XclImpStream& rStrm, sal_uInt16 nMacroSize )
609 maMacroName.clear();
610 rStrm.Ignore( nMacroSize );
613 void XclImpDrawObjBase::ReadMacro8( XclImpStream& rStrm )
615 maMacroName.clear();
616 if( rStrm.GetRecLeft() <= 6 )
617 return;
619 // macro is stored in a tNameXR token containing a link to a defined name
620 sal_uInt16 nFmlaSize;
621 nFmlaSize = rStrm.ReaduInt16();
622 rStrm.Ignore( 4 );
623 OSL_ENSURE( nFmlaSize == 7, "XclImpDrawObjBase::ReadMacro - unexpected formula size" );
624 if( nFmlaSize == 7 )
626 sal_uInt8 nTokenId;
627 sal_uInt16 nExtSheet, nExtName;
628 nTokenId = rStrm.ReaduInt8();
629 nExtSheet = rStrm.ReaduInt16();
630 nExtName = rStrm.ReaduInt16();
631 OSL_ENSURE( nTokenId == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ),
632 "XclImpDrawObjBase::ReadMacro - tNameXR token expected" );
633 if( nTokenId == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ) )
634 maMacroName = GetLinkManager().GetMacroName( nExtSheet, nExtName );
638 void XclImpDrawObjBase::ConvertLineStyle( SdrObject& rSdrObj, const XclObjLineData& rLineData ) const
640 if( rLineData.IsAuto() )
642 XclObjLineData aAutoData;
643 aAutoData.mnAuto = 0;
644 ConvertLineStyle( rSdrObj, aAutoData );
646 else
648 tools::Long nLineWidth = 35 * ::std::min( rLineData.mnWidth, EXC_OBJ_LINE_THICK );
649 rSdrObj.SetMergedItem( XLineWidthItem( nLineWidth ) );
650 rSdrObj.SetMergedItem( XLineColorItem( OUString(), GetPalette().GetColor( rLineData.mnColorIdx ) ) );
651 rSdrObj.SetMergedItem( XLineJointItem( css::drawing::LineJoint_MITER ) );
653 sal_uLong nDotLen = ::std::max< sal_uLong >( 70 * rLineData.mnWidth, 35 );
654 sal_uLong nDashLen = 3 * nDotLen;
655 sal_uLong nDist = 2 * nDotLen;
657 switch( rLineData.mnStyle )
659 default:
660 case EXC_OBJ_LINE_SOLID:
661 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_SOLID ) );
662 break;
663 case EXC_OBJ_LINE_DASH:
664 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_DASH ) );
665 rSdrObj.SetMergedItem( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECT, 0, nDotLen, 1, nDashLen, nDist ) ) );
666 break;
667 case EXC_OBJ_LINE_DOT:
668 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_DASH ) );
669 rSdrObj.SetMergedItem( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECT, 1, nDotLen, 0, nDashLen, nDist ) ) );
670 break;
671 case EXC_OBJ_LINE_DASHDOT:
672 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_DASH ) );
673 rSdrObj.SetMergedItem( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECT, 1, nDotLen, 1, nDashLen, nDist ) ) );
674 break;
675 case EXC_OBJ_LINE_DASHDOTDOT:
676 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_DASH ) );
677 rSdrObj.SetMergedItem( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECT, 2, nDotLen, 1, nDashLen, nDist ) ) );
678 break;
679 case EXC_OBJ_LINE_MEDTRANS:
680 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_SOLID ) );
681 rSdrObj.SetMergedItem( XLineTransparenceItem( 50 ) );
682 break;
683 case EXC_OBJ_LINE_DARKTRANS:
684 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_SOLID ) );
685 rSdrObj.SetMergedItem( XLineTransparenceItem( 25 ) );
686 break;
687 case EXC_OBJ_LINE_LIGHTTRANS:
688 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_SOLID ) );
689 rSdrObj.SetMergedItem( XLineTransparenceItem( 75 ) );
690 break;
691 case EXC_OBJ_LINE_NONE:
692 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_NONE ) );
693 break;
698 void XclImpDrawObjBase::ConvertFillStyle( SdrObject& rSdrObj, const XclObjFillData& rFillData ) const
700 if( rFillData.IsAuto() )
702 XclObjFillData aAutoData;
703 aAutoData.mnAuto = 0;
704 ConvertFillStyle( rSdrObj, aAutoData );
706 else if( rFillData.mnPattern == EXC_PATT_NONE )
708 rSdrObj.SetMergedItem( XFillStyleItem( drawing::FillStyle_NONE ) );
710 else
712 Color aPattColor = GetPalette().GetColor( rFillData.mnPattColorIdx );
713 Color aBackColor = GetPalette().GetColor( rFillData.mnBackColorIdx );
714 if( (rFillData.mnPattern == EXC_PATT_SOLID) || (aPattColor == aBackColor) )
716 rSdrObj.SetMergedItem( XFillStyleItem( drawing::FillStyle_SOLID ) );
717 rSdrObj.SetMergedItem( XFillColorItem( OUString(), aPattColor ) );
719 else
721 static const sal_uInt8 sppnPatterns[][ 8 ] =
723 { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 },
724 { 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD },
725 { 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 },
726 { 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00 },
727 { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC },
728 { 0x33, 0x66, 0xCC, 0x99, 0x33, 0x66, 0xCC, 0x99 },
729 { 0xCC, 0x66, 0x33, 0x99, 0xCC, 0x66, 0x33, 0x99 },
730 { 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33 },
731 { 0xCC, 0xFF, 0x33, 0xFF, 0xCC, 0xFF, 0x33, 0xFF },
732 { 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 },
733 { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 },
734 { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 },
735 { 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 },
736 { 0xFF, 0x11, 0x11, 0x11, 0xFF, 0x11, 0x11, 0x11 },
737 { 0xAA, 0x44, 0xAA, 0x11, 0xAA, 0x44, 0xAA, 0x11 },
738 { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 },
739 { 0x80, 0x00, 0x08, 0x00, 0x80, 0x00, 0x08, 0x00 }
741 const sal_uInt8* const pnPattern = sppnPatterns[std::min<size_t>(rFillData.mnPattern - 2, SAL_N_ELEMENTS(sppnPatterns) - 1)];
742 // create 2-colored 8x8 DIB
743 SvMemoryStream aMemStrm;
744 aMemStrm.WriteUInt32( 12 ).WriteInt16( 8 ).WriteInt16( 8 ).WriteUInt16( 1 ).WriteUInt16( 1 );
745 aMemStrm.WriteUChar( 0xFF ).WriteUChar( 0xFF ).WriteUChar( 0xFF );
746 aMemStrm.WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x00 );
747 for( size_t nIdx = 0; nIdx < 8; ++nIdx )
748 aMemStrm.WriteUInt32( pnPattern[ nIdx ] ); // 32-bit little-endian
749 aMemStrm.Seek( STREAM_SEEK_TO_BEGIN );
750 Bitmap aBitmap;
751 (void)ReadDIB(aBitmap, aMemStrm, false);
753 XOBitmap aXOBitmap(( BitmapEx(aBitmap) ));
754 aXOBitmap.Bitmap2Array();
755 if( aXOBitmap.GetBackgroundColor() == COL_BLACK )
756 ::std::swap( aPattColor, aBackColor );
757 aXOBitmap.SetPixelColor( aPattColor );
758 aXOBitmap.SetBackgroundColor( aBackColor );
759 aXOBitmap.Array2Bitmap();
760 aBitmap = aXOBitmap.GetBitmap().GetBitmap();
762 rSdrObj.SetMergedItem(XFillStyleItem(drawing::FillStyle_BITMAP));
763 rSdrObj.SetMergedItem(XFillBitmapItem(OUString(), Graphic(BitmapEx(aBitmap))));
768 void XclImpDrawObjBase::ConvertFrameStyle( SdrObject& rSdrObj, sal_uInt16 nFrameFlags ) const
770 if( ::get_flag( nFrameFlags, EXC_OBJ_FRAME_SHADOW ) )
772 rSdrObj.SetMergedItem( makeSdrShadowItem( true ) );
773 rSdrObj.SetMergedItem( makeSdrShadowXDistItem( 35 ) );
774 rSdrObj.SetMergedItem( makeSdrShadowYDistItem( 35 ) );
775 rSdrObj.SetMergedItem( makeSdrShadowColorItem( GetPalette().GetColor( EXC_COLOR_WINDOWTEXT ) ) );
779 Color XclImpDrawObjBase::GetSolidLineColor( const XclObjLineData& rLineData ) const
781 Color aColor( COL_TRANSPARENT );
782 if( rLineData.IsAuto() )
784 XclObjLineData aAutoData;
785 aAutoData.mnAuto = 0;
786 aColor = GetSolidLineColor( aAutoData );
788 else if( rLineData.mnStyle != EXC_OBJ_LINE_NONE )
790 aColor = GetPalette().GetColor( rLineData.mnColorIdx );
792 return aColor;
795 Color XclImpDrawObjBase::GetSolidFillColor( const XclObjFillData& rFillData ) const
797 Color aColor( COL_TRANSPARENT );
798 if( rFillData.IsAuto() )
800 XclObjFillData aAutoData;
801 aAutoData.mnAuto = 0;
802 aColor = GetSolidFillColor( aAutoData );
804 else if( rFillData.mnPattern != EXC_PATT_NONE )
806 Color aPattColor = GetPalette().GetColor( rFillData.mnPattColorIdx );
807 Color aBackColor = GetPalette().GetColor( rFillData.mnBackColorIdx );
808 aColor = XclTools::GetPatternColor( aPattColor, aBackColor, rFillData.mnPattern );
810 return aColor;
813 void XclImpDrawObjBase::DoReadObj3( XclImpStream&, sal_uInt16 )
817 void XclImpDrawObjBase::DoReadObj4( XclImpStream&, sal_uInt16 )
821 void XclImpDrawObjBase::DoReadObj5( XclImpStream&, sal_uInt16, sal_uInt16 )
825 void XclImpDrawObjBase::DoReadObj8SubRec( XclImpStream&, sal_uInt16, sal_uInt16 )
829 std::size_t XclImpDrawObjBase::DoGetProgressSize() const
831 return 1;
834 rtl::Reference<SdrObject> XclImpDrawObjBase::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& ) const
836 rDffConv.Progress( GetProgressSize() );
837 return nullptr;
840 void XclImpDrawObjBase::DoPreProcessSdrObj( XclImpDffConverter&, SdrObject& ) const
842 // trace if object is not printable
843 if( !IsPrintable() )
844 GetTracer().TraceObjectNotPrintable();
847 void XclImpDrawObjBase::DoPostProcessSdrObj( XclImpDffConverter&, SdrObject& ) const
851 void XclImpDrawObjBase::ImplReadObj3( XclImpStream& rStrm )
853 // back to offset 4 (ignore object count field)
854 rStrm.Seek( 4 );
856 sal_uInt16 nObjFlags, nMacroSize;
857 mnObjType = rStrm.ReaduInt16();
858 mnObjId = rStrm.ReaduInt16();
859 nObjFlags = rStrm.ReaduInt16();
860 rStrm >> maAnchor;
861 nMacroSize = rStrm.ReaduInt16();
862 rStrm.Ignore( 2 );
864 mbHasAnchor = true;
865 mbHidden = ::get_flag( nObjFlags, EXC_OBJ_HIDDEN );
866 mbVisible = ::get_flag( nObjFlags, EXC_OBJ_VISIBLE );
867 DoReadObj3( rStrm, nMacroSize );
870 void XclImpDrawObjBase::ImplReadObj4( XclImpStream& rStrm )
872 // back to offset 4 (ignore object count field)
873 rStrm.Seek( 4 );
875 sal_uInt16 nObjFlags, nMacroSize;
876 mnObjType = rStrm.ReaduInt16();
877 mnObjId = rStrm.ReaduInt16();
878 nObjFlags = rStrm.ReaduInt16();
879 rStrm >> maAnchor;
880 nMacroSize = rStrm.ReaduInt16();
881 rStrm.Ignore( 2 );
883 mbHasAnchor = true;
884 mbHidden = ::get_flag( nObjFlags, EXC_OBJ_HIDDEN );
885 mbVisible = ::get_flag( nObjFlags, EXC_OBJ_VISIBLE );
886 mbPrintable = ::get_flag( nObjFlags, EXC_OBJ_PRINTABLE );
887 DoReadObj4( rStrm, nMacroSize );
890 void XclImpDrawObjBase::ImplReadObj5( XclImpStream& rStrm )
892 // back to offset 4 (ignore object count field)
893 rStrm.Seek( 4 );
895 sal_uInt16 nObjFlags, nMacroSize, nNameLen;
896 mnObjType = rStrm.ReaduInt16();
897 mnObjId = rStrm.ReaduInt16();
898 nObjFlags = rStrm.ReaduInt16();
899 rStrm >> maAnchor;
900 nMacroSize = rStrm.ReaduInt16();
901 rStrm.Ignore( 2 );
902 nNameLen = rStrm.ReaduInt16();
903 rStrm.Ignore( 2 );
905 mbHasAnchor = true;
906 mbHidden = ::get_flag( nObjFlags, EXC_OBJ_HIDDEN );
907 mbVisible = ::get_flag( nObjFlags, EXC_OBJ_VISIBLE );
908 mbPrintable = ::get_flag( nObjFlags, EXC_OBJ_PRINTABLE );
909 DoReadObj5( rStrm, nNameLen, nMacroSize );
912 void XclImpDrawObjBase::ImplReadObj8( XclImpStream& rStrm )
914 // back to beginning
915 rStrm.Seek( EXC_REC_SEEK_TO_BEGIN );
917 bool bLoop = true;
918 while (bLoop)
920 if (rStrm.GetRecLeft() < 4)
921 break;
923 sal_uInt16 nSubRecId = rStrm.ReaduInt16();
924 sal_uInt16 nSubRecSize = rStrm.ReaduInt16();
925 rStrm.PushPosition();
926 // sometimes the last subrecord has an invalid length (OBJLBSDATA) -> min()
927 nSubRecSize = static_cast< sal_uInt16 >( ::std::min< std::size_t >( nSubRecSize, rStrm.GetRecLeft() ) );
929 switch( nSubRecId )
931 case EXC_ID_OBJCMO:
932 OSL_ENSURE( rStrm.GetRecPos() == 4, "XclImpDrawObjBase::ImplReadObj8 - unexpected OBJCMO subrecord" );
933 if( (rStrm.GetRecPos() == 4) && (nSubRecSize >= 6) )
935 sal_uInt16 nObjFlags;
936 mnObjType = rStrm.ReaduInt16();
937 mnObjId = rStrm.ReaduInt16( );
938 nObjFlags = rStrm.ReaduInt16( );
939 mbPrintable = ::get_flag( nObjFlags, EXC_OBJCMO_PRINTABLE );
941 break;
942 case EXC_ID_OBJMACRO:
943 ReadMacro8( rStrm );
944 break;
945 case EXC_ID_OBJEND:
946 bLoop = false;
947 break;
948 default:
949 DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
952 rStrm.PopPosition();
953 rStrm.Ignore( nSubRecSize );
956 /* Call DoReadObj8SubRec() with EXC_ID_OBJEND for further stream
957 processing (e.g. charts), even if the OBJEND subrecord is missing. */
958 DoReadObj8SubRec( rStrm, EXC_ID_OBJEND, 0 );
960 /* Pictures that Excel reads from BIFF5 and writes to BIFF8 still have the
961 IMGDATA record following the OBJ record (but they use the image data
962 stored in DFF). The IMGDATA record may be continued by several CONTINUE
963 records. But the last CONTINUE record may be in fact an MSODRAWING
964 record that contains the DFF data of the next drawing object! So we
965 have to skip just enough CONTINUE records to look at the next
966 MSODRAWING/CONTINUE record. */
967 if( !((rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord()) )
968 return;
970 rStrm.Ignore( 4 );
971 sal_uInt32 nDataSize = rStrm.ReaduInt32();
972 nDataSize -= rStrm.GetRecLeft();
973 // skip following CONTINUE records until IMGDATA ends
974 while (true)
976 if (!nDataSize)
977 break;
978 if (rStrm.GetNextRecId() != EXC_ID_CONT)
979 break;
980 if (!rStrm.StartNextRecord())
981 break;
982 OSL_ENSURE( nDataSize >= rStrm.GetRecLeft(), "XclImpDrawObjBase::ImplReadObj8 - CONTINUE too long" );
983 nDataSize -= ::std::min< sal_uInt32 >( rStrm.GetRecLeft(), nDataSize );
985 OSL_ENSURE( nDataSize == 0, "XclImpDrawObjBase::ImplReadObj8 - missing CONTINUE records" );
986 // next record may be MSODRAWING or CONTINUE or anything else
989 void XclImpDrawObjVector::InsertGrouped( XclImpDrawObjRef const & xDrawObj )
991 if( !mObjs.empty() )
992 if( XclImpGroupObj* pGroupObj = dynamic_cast< XclImpGroupObj* >( mObjs.back().get() ) )
993 if( pGroupObj->TryInsert( xDrawObj ) )
994 return;
995 mObjs.push_back( xDrawObj );
998 std::size_t XclImpDrawObjVector::GetProgressSize() const
1000 return std::accumulate(mObjs.begin(), mObjs.end(), std::size_t(0),
1001 [](const std::size_t& rSum, const XclImpDrawObjRef& rxObj) { return rSum + rxObj->GetProgressSize(); });
1004 XclImpPhObj::XclImpPhObj( const XclImpRoot& rRoot ) :
1005 XclImpDrawObjBase( rRoot )
1007 SetProcessSdrObj( false );
1010 XclImpGroupObj::XclImpGroupObj( const XclImpRoot& rRoot ) :
1011 XclImpDrawObjBase( rRoot ),
1012 mnFirstUngrouped( 0 )
1016 bool XclImpGroupObj::TryInsert( XclImpDrawObjRef const & xDrawObj )
1018 if( xDrawObj->GetObjId() == mnFirstUngrouped )
1019 return false;
1020 // insert into own list or into nested group
1021 maChildren.InsertGrouped( xDrawObj );
1022 return true;
1025 void XclImpGroupObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1027 rStrm.Ignore( 4 );
1028 mnFirstUngrouped = rStrm.ReaduInt16();
1029 rStrm.Ignore( 16 );
1030 ReadMacro3( rStrm, nMacroSize );
1033 void XclImpGroupObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1035 rStrm.Ignore( 4 );
1036 mnFirstUngrouped = rStrm.ReaduInt16();
1037 rStrm.Ignore( 16 );
1038 ReadMacro4( rStrm, nMacroSize );
1041 void XclImpGroupObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1043 rStrm.Ignore( 4 );
1044 mnFirstUngrouped = rStrm.ReaduInt16();
1045 rStrm.Ignore( 16 );
1046 ReadName5( rStrm, nNameLen );
1047 ReadMacro5( rStrm, nMacroSize );
1050 std::size_t XclImpGroupObj::DoGetProgressSize() const
1052 return XclImpDrawObjBase::DoGetProgressSize() + maChildren.GetProgressSize();
1055 rtl::Reference<SdrObject> XclImpGroupObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& /*rAnchorRect*/ ) const
1057 rtl::Reference<SdrObjGroup> xSdrObj(
1058 new SdrObjGroup(
1059 *GetDoc().GetDrawLayer()));
1060 // child objects in BIFF2-BIFF5 have absolute size, not needed to pass own anchor rectangle
1061 SdrObjList& rObjList = *xSdrObj->GetSubList(); // SdrObjGroup always returns existing sublist
1062 for( const auto& rxChild : maChildren )
1063 rDffConv.ProcessObject( rObjList, *rxChild );
1064 rDffConv.Progress();
1065 return xSdrObj;
1068 XclImpLineObj::XclImpLineObj( const XclImpRoot& rRoot ) :
1069 XclImpDrawObjBase( rRoot ),
1070 mnArrows( 0 ),
1071 mnStartPoint( EXC_OBJ_LINE_TL )
1073 SetAreaObj( false );
1076 void XclImpLineObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1078 rStrm >> maLineData;
1079 mnArrows = rStrm.ReaduInt16();
1080 mnStartPoint = rStrm.ReaduInt8();
1081 rStrm.Ignore( 1 );
1082 ReadMacro3( rStrm, nMacroSize );
1085 void XclImpLineObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1087 rStrm >> maLineData;
1088 mnArrows = rStrm.ReaduInt16();
1089 mnStartPoint = rStrm.ReaduInt8();
1090 rStrm.Ignore( 1 );
1091 ReadMacro4( rStrm, nMacroSize );
1094 void XclImpLineObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1096 rStrm >> maLineData;
1097 mnArrows = rStrm.ReaduInt16();
1098 mnStartPoint = rStrm.ReaduInt8();
1099 rStrm.Ignore( 1 );
1100 ReadName5( rStrm, nNameLen );
1101 ReadMacro5( rStrm, nMacroSize );
1104 rtl::Reference<SdrObject> XclImpLineObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1106 ::basegfx::B2DPolygon aB2DPolygon;
1107 switch( mnStartPoint )
1109 default:
1110 case EXC_OBJ_LINE_TL:
1111 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Top() ) );
1112 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Bottom() ) );
1113 break;
1114 case EXC_OBJ_LINE_TR:
1115 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Top() ) );
1116 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Bottom() ) );
1117 break;
1118 case EXC_OBJ_LINE_BR:
1119 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Bottom() ) );
1120 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Top() ) );
1121 break;
1122 case EXC_OBJ_LINE_BL:
1123 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Bottom() ) );
1124 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Top() ) );
1125 break;
1127 rtl::Reference<SdrObject> xSdrObj(
1128 new SdrPathObj(
1129 *GetDoc().GetDrawLayer(),
1130 SdrObjKind::Line,
1131 ::basegfx::B2DPolyPolygon(aB2DPolygon)));
1132 ConvertLineStyle( *xSdrObj, maLineData );
1134 // line ends
1135 sal_uInt8 nArrowType = ::extract_value< sal_uInt8 >( mnArrows, 0, 4 );
1136 bool bLineStart = false;
1137 bool bLineEnd = false;
1138 bool bFilled = false;
1139 switch( nArrowType )
1141 case EXC_OBJ_ARROW_OPEN: bLineStart = false; bLineEnd = true; bFilled = false; break;
1142 case EXC_OBJ_ARROW_OPENBOTH: bLineStart = true; bLineEnd = true; bFilled = false; break;
1143 case EXC_OBJ_ARROW_FILLED: bLineStart = false; bLineEnd = true; bFilled = true; break;
1144 case EXC_OBJ_ARROW_FILLEDBOTH: bLineStart = true; bLineEnd = true; bFilled = true; break;
1146 if( bLineStart || bLineEnd )
1148 sal_uInt8 nArrowWidth = ::extract_value< sal_uInt8 >( mnArrows, 4, 4 );
1149 double fArrowWidth = 3.0;
1150 switch( nArrowWidth )
1152 case EXC_OBJ_ARROW_NARROW: fArrowWidth = 2.0; break;
1153 case EXC_OBJ_ARROW_MEDIUM: fArrowWidth = 3.0; break;
1154 case EXC_OBJ_ARROW_WIDE: fArrowWidth = 5.0; break;
1157 sal_uInt8 nArrowLength = ::extract_value< sal_uInt8 >( mnArrows, 8, 4 );
1158 double fArrowLength = 3.0;
1159 switch( nArrowLength )
1161 case EXC_OBJ_ARROW_NARROW: fArrowLength = 2.5; break;
1162 case EXC_OBJ_ARROW_MEDIUM: fArrowLength = 3.5; break;
1163 case EXC_OBJ_ARROW_WIDE: fArrowLength = 6.0; break;
1166 ::basegfx::B2DPolygon aArrowPoly;
1167 #define EXC_ARROW_POINT( x, y ) ::basegfx::B2DPoint( fArrowWidth * (x), fArrowLength * (y) )
1168 if( bFilled )
1170 aArrowPoly.append( EXC_ARROW_POINT( 0, 100 ) );
1171 aArrowPoly.append( EXC_ARROW_POINT( 50, 0 ) );
1172 aArrowPoly.append( EXC_ARROW_POINT( 100, 100 ) );
1174 else
1176 sal_uInt8 nLineWidth = ::limit_cast< sal_uInt8 >( maLineData.mnWidth, EXC_OBJ_LINE_THIN, EXC_OBJ_LINE_THICK );
1177 aArrowPoly.append( EXC_ARROW_POINT( 50, 0 ) );
1178 aArrowPoly.append( EXC_ARROW_POINT( 100, 100 - 3 * nLineWidth ) );
1179 aArrowPoly.append( EXC_ARROW_POINT( 100 - 5 * nLineWidth, 100 ) );
1180 aArrowPoly.append( EXC_ARROW_POINT( 50, 12 * nLineWidth ) );
1181 aArrowPoly.append( EXC_ARROW_POINT( 5 * nLineWidth, 100 ) );
1182 aArrowPoly.append( EXC_ARROW_POINT( 0, 100 - 3 * nLineWidth ) );
1184 #undef EXC_ARROW_POINT
1186 tools::Long nWidth = static_cast< tools::Long >( 125 * fArrowWidth );
1187 if( bLineStart )
1189 xSdrObj->SetMergedItem( XLineStartItem( OUString(), basegfx::B2DPolyPolygon(aArrowPoly) ) );
1190 xSdrObj->SetMergedItem( XLineStartWidthItem( nWidth ) );
1191 xSdrObj->SetMergedItem( XLineStartCenterItem( false ) );
1193 if( bLineEnd )
1195 xSdrObj->SetMergedItem( XLineEndItem( OUString(), basegfx::B2DPolyPolygon(aArrowPoly) ) );
1196 xSdrObj->SetMergedItem( XLineEndWidthItem( nWidth ) );
1197 xSdrObj->SetMergedItem( XLineEndCenterItem( false ) );
1200 rDffConv.Progress();
1201 return xSdrObj;
1204 XclImpRectObj::XclImpRectObj( const XclImpRoot& rRoot ) :
1205 XclImpDrawObjBase( rRoot ),
1206 mnFrameFlags( 0 )
1208 SetAreaObj( true );
1211 void XclImpRectObj::ReadFrameData( XclImpStream& rStrm )
1213 rStrm >> maFillData >> maLineData;
1214 mnFrameFlags = rStrm.ReaduInt16();
1217 void XclImpRectObj::ConvertRectStyle( SdrObject& rSdrObj ) const
1219 ConvertLineStyle( rSdrObj, maLineData );
1220 ConvertFillStyle( rSdrObj, maFillData );
1221 ConvertFrameStyle( rSdrObj, mnFrameFlags );
1224 void XclImpRectObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1226 ReadFrameData( rStrm );
1227 ReadMacro3( rStrm, nMacroSize );
1230 void XclImpRectObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1232 ReadFrameData( rStrm );
1233 ReadMacro4( rStrm, nMacroSize );
1236 void XclImpRectObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1238 ReadFrameData( rStrm );
1239 ReadName5( rStrm, nNameLen );
1240 ReadMacro5( rStrm, nMacroSize );
1243 rtl::Reference<SdrObject> XclImpRectObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1245 rtl::Reference<SdrObject> xSdrObj(
1246 new SdrRectObj(
1247 *GetDoc().GetDrawLayer(),
1248 rAnchorRect));
1249 ConvertRectStyle( *xSdrObj );
1250 rDffConv.Progress();
1251 return xSdrObj;
1254 XclImpOvalObj::XclImpOvalObj( const XclImpRoot& rRoot ) :
1255 XclImpRectObj( rRoot )
1259 rtl::Reference<SdrObject> XclImpOvalObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1261 rtl::Reference<SdrObject> xSdrObj(
1262 new SdrCircObj(
1263 *GetDoc().GetDrawLayer(),
1264 SdrCircKind::Full,
1265 rAnchorRect));
1266 ConvertRectStyle( *xSdrObj );
1267 rDffConv.Progress();
1268 return xSdrObj;
1271 XclImpArcObj::XclImpArcObj( const XclImpRoot& rRoot ) :
1272 XclImpDrawObjBase( rRoot ),
1273 mnQuadrant( EXC_OBJ_ARC_TR )
1275 SetAreaObj( false ); // arc may be 2-dimensional
1278 void XclImpArcObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1280 rStrm >> maFillData >> maLineData;
1281 mnQuadrant = rStrm.ReaduInt8();
1282 rStrm.Ignore( 1 );
1283 ReadMacro3( rStrm, nMacroSize );
1286 void XclImpArcObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1288 rStrm >> maFillData >> maLineData;
1289 mnQuadrant = rStrm.ReaduInt8();
1290 rStrm.Ignore( 1 );
1291 ReadMacro4( rStrm, nMacroSize );
1294 void XclImpArcObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1296 rStrm >> maFillData >> maLineData;
1297 mnQuadrant = rStrm.ReaduInt8();
1298 rStrm.Ignore( 1 );
1299 ReadName5( rStrm, nNameLen );
1300 ReadMacro5( rStrm, nMacroSize );
1303 rtl::Reference<SdrObject> XclImpArcObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1305 tools::Rectangle aNewRect = rAnchorRect;
1306 Degree100 nStartAngle;
1307 Degree100 nEndAngle;
1308 switch( mnQuadrant )
1310 default:
1311 case EXC_OBJ_ARC_TR:
1312 nStartAngle = 0_deg100;
1313 nEndAngle = 9000_deg100;
1314 aNewRect.AdjustLeft( -(rAnchorRect.GetWidth()) );
1315 aNewRect.AdjustBottom(rAnchorRect.GetHeight() );
1316 break;
1317 case EXC_OBJ_ARC_TL:
1318 nStartAngle = 9000_deg100;
1319 nEndAngle = 18000_deg100;
1320 aNewRect.AdjustRight(rAnchorRect.GetWidth() );
1321 aNewRect.AdjustBottom(rAnchorRect.GetHeight() );
1322 break;
1323 case EXC_OBJ_ARC_BL:
1324 nStartAngle = 18000_deg100;
1325 nEndAngle = 27000_deg100;
1326 aNewRect.AdjustRight(rAnchorRect.GetWidth() );
1327 aNewRect.AdjustTop( -(rAnchorRect.GetHeight()) );
1328 break;
1329 case EXC_OBJ_ARC_BR:
1330 nStartAngle = 27000_deg100;
1331 nEndAngle = 0_deg100;
1332 aNewRect.AdjustLeft( -(rAnchorRect.GetWidth()) );
1333 aNewRect.AdjustTop( -(rAnchorRect.GetHeight()) );
1334 break;
1336 SdrCircKind eObjKind = maFillData.IsFilled() ? SdrCircKind::Section : SdrCircKind::Arc;
1337 rtl::Reference<SdrObject> xSdrObj(
1338 new SdrCircObj(
1339 *GetDoc().GetDrawLayer(),
1340 eObjKind,
1341 aNewRect,
1342 nStartAngle,
1343 nEndAngle));
1344 ConvertFillStyle( *xSdrObj, maFillData );
1345 ConvertLineStyle( *xSdrObj, maLineData );
1346 rDffConv.Progress();
1347 return xSdrObj;
1350 XclImpPolygonObj::XclImpPolygonObj( const XclImpRoot& rRoot ) :
1351 XclImpRectObj( rRoot ),
1352 mnPolyFlags( 0 ),
1353 mnPointCount( 0 )
1355 SetAreaObj( false ); // polygon may be 2-dimensional
1358 void XclImpPolygonObj::ReadCoordList( XclImpStream& rStrm )
1360 if( (rStrm.GetNextRecId() == EXC_ID_COORDLIST) && rStrm.StartNextRecord() )
1362 OSL_ENSURE( rStrm.GetRecLeft() / 4 == mnPointCount, "XclImpPolygonObj::ReadCoordList - wrong polygon point count" );
1363 while (true)
1365 if (rStrm.GetRecLeft() < 4)
1366 break;
1367 sal_uInt16 nX = rStrm.ReaduInt16();
1368 sal_uInt16 nY = rStrm.ReaduInt16();
1369 maCoords.emplace_back( nX, nY );
1374 void XclImpPolygonObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1376 ReadFrameData( rStrm );
1377 mnPolyFlags = rStrm.ReaduInt16();
1378 rStrm.Ignore( 10 );
1379 mnPointCount = rStrm.ReaduInt16();
1380 rStrm.Ignore( 8 );
1381 ReadMacro4( rStrm, nMacroSize );
1382 ReadCoordList( rStrm );
1385 void XclImpPolygonObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1387 ReadFrameData( rStrm );
1388 mnPolyFlags = rStrm.ReaduInt16();
1389 rStrm.Ignore( 10 );
1390 mnPointCount = rStrm.ReaduInt16();
1391 rStrm.Ignore( 8 );
1392 ReadName5( rStrm, nNameLen );
1393 ReadMacro5( rStrm, nMacroSize );
1394 ReadCoordList( rStrm );
1397 namespace {
1399 ::basegfx::B2DPoint lclGetPolyPoint( const tools::Rectangle& rAnchorRect, const Point& rPoint )
1401 return ::basegfx::B2DPoint(
1402 rAnchorRect.Left() + static_cast< sal_Int32 >( ::std::min< double >( rPoint.X(), 16384.0 ) / 16384.0 * rAnchorRect.GetWidth() + 0.5 ),
1403 rAnchorRect.Top() + static_cast< sal_Int32 >( ::std::min< double >( rPoint.Y(), 16384.0 ) / 16384.0 * rAnchorRect.GetHeight() + 0.5 ) );
1406 } // namespace
1408 rtl::Reference<SdrObject> XclImpPolygonObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1410 rtl::Reference<SdrObject> xSdrObj;
1411 if( maCoords.size() >= 2 )
1413 // create the polygon
1414 ::basegfx::B2DPolygon aB2DPolygon;
1415 for( const auto& rCoord : maCoords )
1416 aB2DPolygon.append( lclGetPolyPoint( rAnchorRect, rCoord ) );
1417 // close polygon if specified
1418 if( ::get_flag( mnPolyFlags, EXC_OBJ_POLY_CLOSED ) && (maCoords.front() != maCoords.back()) )
1419 aB2DPolygon.append( lclGetPolyPoint( rAnchorRect, maCoords.front() ) );
1420 // create the SdrObject
1421 SdrObjKind eObjKind = maFillData.IsFilled() ? SdrObjKind::PathPoly : SdrObjKind::PathPolyLine;
1422 xSdrObj =
1423 new SdrPathObj(
1424 *GetDoc().GetDrawLayer(),
1425 eObjKind,
1426 ::basegfx::B2DPolyPolygon(aB2DPolygon));
1427 ConvertRectStyle( *xSdrObj );
1429 rDffConv.Progress();
1430 return xSdrObj;
1433 void XclImpObjTextData::ReadByteString( XclImpStream& rStrm )
1435 mxString.reset();
1436 if( maData.mnTextLen > 0 )
1438 mxString = std::make_shared<XclImpString>( rStrm.ReadRawByteString( maData.mnTextLen ) );
1439 // skip padding byte for word boundaries
1440 if( rStrm.GetRecPos() & 1 ) rStrm.Ignore( 1 );
1444 void XclImpObjTextData::ReadFormats( XclImpStream& rStrm )
1446 if( mxString )
1447 mxString->ReadObjFormats( rStrm, maData.mnFormatSize );
1448 else
1449 rStrm.Ignore( maData.mnFormatSize );
1452 XclImpTextObj::XclImpTextObj( const XclImpRoot& rRoot ) :
1453 XclImpRectObj( rRoot )
1457 void XclImpTextObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1459 ReadFrameData( rStrm );
1460 maTextData.maData.ReadObj3( rStrm );
1461 ReadMacro3( rStrm, nMacroSize );
1462 maTextData.ReadByteString( rStrm );
1463 maTextData.ReadFormats( rStrm );
1466 void XclImpTextObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1468 ReadFrameData( rStrm );
1469 maTextData.maData.ReadObj3( rStrm );
1470 ReadMacro4( rStrm, nMacroSize );
1471 maTextData.ReadByteString( rStrm );
1472 maTextData.ReadFormats( rStrm );
1475 void XclImpTextObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1477 ReadFrameData( rStrm );
1478 maTextData.maData.ReadObj5( rStrm );
1479 ReadName5( rStrm, nNameLen );
1480 ReadMacro5( rStrm, nMacroSize );
1481 maTextData.ReadByteString( rStrm );
1482 rStrm.Ignore( maTextData.maData.mnLinkSize ); // ignore text link formula
1483 maTextData.ReadFormats( rStrm );
1486 rtl::Reference<SdrObject> XclImpTextObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1488 rtl::Reference<SdrObjCustomShape> xSdrObj(
1489 new SdrObjCustomShape(
1490 *GetDoc().GetDrawLayer()));
1491 xSdrObj->NbcSetSnapRect( rAnchorRect );
1492 OUString aRectType = u"rectangle"_ustr;
1493 xSdrObj->MergeDefaultAttributes( &aRectType );
1494 ConvertRectStyle( *xSdrObj );
1495 bool bAutoSize = ::get_flag( maTextData.maData.mnFlags, EXC_OBJ_TEXT_AUTOSIZE );
1496 xSdrObj->SetMergedItem( makeSdrTextAutoGrowWidthItem( bAutoSize ) );
1497 xSdrObj->SetMergedItem( makeSdrTextAutoGrowHeightItem( bAutoSize ) );
1498 xSdrObj->SetMergedItem( makeSdrTextWordWrapItem( true ) );
1499 rDffConv.Progress();
1500 return xSdrObj;
1503 void XclImpTextObj::DoPreProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const
1505 // set text data
1506 if( SdrTextObj* pTextObj = DynCastSdrTextObj( &rSdrObj ) )
1508 if( maTextData.mxString )
1510 if( maTextData.mxString->IsRich() )
1512 if (maTextData.mxString->GetText().getLength() > 1024 && comphelper::IsFuzzing())
1514 SAL_WARN("sc.filter", "truncating slow long rich text for fuzzing performance");
1515 maTextData.mxString->SetText(maTextData.mxString->GetText().copy(0, 1024));
1518 // rich text
1519 std::unique_ptr< EditTextObject > xEditObj(
1520 XclImpStringHelper::CreateTextObject( GetRoot(), *maTextData.mxString ) );
1521 OutlinerParaObject aOutlineObj(std::move(xEditObj));
1522 aOutlineObj.SetOutlinerMode( OutlinerMode::TextObject );
1523 pTextObj->NbcSetOutlinerParaObject( std::move(aOutlineObj) );
1525 else
1527 // plain text
1528 pTextObj->NbcSetText( maTextData.mxString->GetText() );
1531 /* #i96858# Do not apply any formatting if there is no text.
1532 SdrObjCustomShape::SetVerticalWriting (initiated from
1533 SetMergedItem) calls SdrTextObj::ForceOutlinerParaObject which
1534 ensures that we can erroneously write a ClientTextbox record
1535 (with no content) while exporting to XLS, which can cause a
1536 corrupted exported document. */
1538 SvxAdjust eHorAlign = SvxAdjust::Left;
1539 SdrTextVertAdjust eVerAlign = SDRTEXTVERTADJUST_TOP;
1541 // orientation (this is only a fake, drawing does not support real text orientation)
1542 namespace csst = css::text;
1543 csst::WritingMode eWriteMode = csst::WritingMode_LR_TB;
1544 switch( maTextData.maData.mnOrient )
1546 default:
1547 case EXC_OBJ_ORIENT_NONE:
1549 eWriteMode = csst::WritingMode_LR_TB;
1550 switch( maTextData.maData.GetHorAlign() )
1552 case EXC_OBJ_HOR_LEFT: eHorAlign = SvxAdjust::Left; break;
1553 case EXC_OBJ_HOR_CENTER: eHorAlign = SvxAdjust::Center; break;
1554 case EXC_OBJ_HOR_RIGHT: eHorAlign = SvxAdjust::Right; break;
1555 case EXC_OBJ_HOR_JUSTIFY: eHorAlign = SvxAdjust::Block; break;
1557 switch( maTextData.maData.GetVerAlign() )
1559 case EXC_OBJ_VER_TOP: eVerAlign = SDRTEXTVERTADJUST_TOP; break;
1560 case EXC_OBJ_VER_CENTER: eVerAlign = SDRTEXTVERTADJUST_CENTER; break;
1561 case EXC_OBJ_VER_BOTTOM: eVerAlign = SDRTEXTVERTADJUST_BOTTOM; break;
1562 case EXC_OBJ_VER_JUSTIFY: eVerAlign = SDRTEXTVERTADJUST_BLOCK; break;
1565 break;
1567 case EXC_OBJ_ORIENT_90CCW:
1569 if( SdrObjCustomShape* pObjCustomShape = dynamic_cast< SdrObjCustomShape* >( &rSdrObj ) )
1571 css::beans::PropertyValue aTextRotateAngle;
1572 aTextRotateAngle.Name = "TextRotateAngle";
1573 aTextRotateAngle.Value <<= 180.0;
1574 SdrCustomShapeGeometryItem aGeometryItem(pObjCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ));
1575 aGeometryItem.SetPropertyValue( aTextRotateAngle );
1576 pObjCustomShape->SetMergedItem( aGeometryItem );
1578 eWriteMode = csst::WritingMode_TB_RL;
1579 switch( maTextData.maData.GetHorAlign() )
1581 case EXC_OBJ_HOR_LEFT: eVerAlign = SDRTEXTVERTADJUST_TOP; break;
1582 case EXC_OBJ_HOR_CENTER: eVerAlign = SDRTEXTVERTADJUST_CENTER; break;
1583 case EXC_OBJ_HOR_RIGHT: eVerAlign = SDRTEXTVERTADJUST_BOTTOM; break;
1584 case EXC_OBJ_HOR_JUSTIFY: eVerAlign = SDRTEXTVERTADJUST_BLOCK; break;
1586 MSO_Anchor eTextAnchor = static_cast<MSO_Anchor>(rDffConv.GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop ));
1587 switch( eTextAnchor )
1589 case mso_anchorTopCentered :
1590 case mso_anchorMiddleCentered :
1591 case mso_anchorBottomCentered :
1593 eHorAlign = SvxAdjust::Center;
1595 break;
1597 default:
1599 switch( maTextData.maData.GetVerAlign() )
1601 case EXC_OBJ_VER_TOP: eHorAlign = SvxAdjust::Right; break;
1602 case EXC_OBJ_VER_CENTER: eHorAlign = SvxAdjust::Center; break;
1603 case EXC_OBJ_VER_BOTTOM: eHorAlign = SvxAdjust::Left; break;
1604 case EXC_OBJ_VER_JUSTIFY: eHorAlign = SvxAdjust::Block; break;
1609 break;
1611 case EXC_OBJ_ORIENT_STACKED:
1613 // sj: STACKED is not supported, maybe it can be optimized here a bit
1614 [[fallthrough]];
1616 case EXC_OBJ_ORIENT_90CW:
1618 eWriteMode = csst::WritingMode_TB_RL;
1619 switch( maTextData.maData.GetHorAlign() )
1621 case EXC_OBJ_HOR_LEFT: eVerAlign = SDRTEXTVERTADJUST_BOTTOM; break;
1622 case EXC_OBJ_HOR_CENTER: eVerAlign = SDRTEXTVERTADJUST_CENTER; break;
1623 case EXC_OBJ_HOR_RIGHT: eVerAlign = SDRTEXTVERTADJUST_TOP; break;
1624 case EXC_OBJ_HOR_JUSTIFY: eVerAlign = SDRTEXTVERTADJUST_BLOCK; break;
1626 MSO_Anchor eTextAnchor = static_cast<MSO_Anchor>(rDffConv.GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop ));
1627 switch ( eTextAnchor )
1629 case mso_anchorTopCentered :
1630 case mso_anchorMiddleCentered :
1631 case mso_anchorBottomCentered :
1633 eHorAlign = SvxAdjust::Center;
1635 break;
1637 default:
1639 switch( maTextData.maData.GetVerAlign() )
1641 case EXC_OBJ_VER_TOP: eHorAlign = SvxAdjust::Left; break;
1642 case EXC_OBJ_VER_CENTER: eHorAlign = SvxAdjust::Center; break;
1643 case EXC_OBJ_VER_BOTTOM: eHorAlign = SvxAdjust::Right; break;
1644 case EXC_OBJ_VER_JUSTIFY: eHorAlign = SvxAdjust::Block; break;
1649 break;
1651 rSdrObj.SetMergedItem( SvxAdjustItem( eHorAlign, EE_PARA_JUST ) );
1652 rSdrObj.SetMergedItem( SdrTextVertAdjustItem( eVerAlign ) );
1653 rSdrObj.SetMergedItem( SvxWritingModeItem( eWriteMode, SDRATTR_TEXTDIRECTION ) );
1656 // base class processing
1657 XclImpRectObj::DoPreProcessSdrObj( rDffConv, rSdrObj );
1660 XclImpChartObj::XclImpChartObj( const XclImpRoot& rRoot, bool bOwnTab ) :
1661 XclImpRectObj( rRoot ),
1662 mbOwnTab( bOwnTab )
1664 SetSimpleMacro( false );
1665 SetCustomDffObj( true );
1668 void XclImpChartObj::ReadChartSubStream( XclImpStream& rStrm )
1670 /* If chart is read from a chartsheet (mbOwnTab == true), the BOF record
1671 has already been read. If chart is embedded as object, the next record
1672 has to be the BOF record. */
1673 if( mbOwnTab )
1675 /* #i109800# The input stream may point somewhere inside the chart
1676 substream and not exactly to the leading BOF record. To read this
1677 record correctly in the following, the stream has to rewind it, so
1678 that the next call to StartNextRecord() will find it correctly. */
1679 if( rStrm.GetRecId() != EXC_ID5_BOF )
1680 rStrm.RewindRecord();
1682 else
1684 if( (rStrm.GetNextRecId() == EXC_ID5_BOF) && rStrm.StartNextRecord() )
1686 sal_uInt16 nBofType;
1687 rStrm.Seek( 2 );
1688 nBofType = rStrm.ReaduInt16();
1689 SAL_WARN_IF( nBofType != EXC_BOF_CHART, "sc.filter", "XclImpChartObj::ReadChartSubStream - no chart BOF record" );
1691 else
1693 SAL_INFO("sc.filter", "XclImpChartObj::ReadChartSubStream - missing chart substream");
1694 return;
1698 // read chart, even if BOF record contains wrong substream identifier
1699 mxChart = std::make_shared<XclImpChart>( GetRoot(), mbOwnTab );
1700 mxChart->ReadChartSubStream( rStrm );
1701 if( mbOwnTab )
1702 FinalizeTabChart();
1705 void XclImpChartObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1707 // read OBJ record and the following chart substream
1708 ReadFrameData( rStrm );
1709 rStrm.Ignore( 18 );
1710 ReadMacro3( rStrm, nMacroSize );
1711 // set frame format from OBJ record, it is used if chart itself is transparent
1712 if( mxChart )
1713 mxChart->UpdateObjFrame( maLineData, maFillData );
1716 void XclImpChartObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1718 // read OBJ record and the following chart substream
1719 ReadFrameData( rStrm );
1720 rStrm.Ignore( 18 );
1721 ReadMacro4( rStrm, nMacroSize );
1722 // set frame format from OBJ record, it is used if chart itself is transparent
1723 if( mxChart )
1724 mxChart->UpdateObjFrame( maLineData, maFillData );
1727 void XclImpChartObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1729 // read OBJ record and the following chart substream
1730 ReadFrameData( rStrm );
1731 rStrm.Ignore( 18 );
1732 ReadName5( rStrm, nNameLen );
1733 ReadMacro5( rStrm, nMacroSize );
1734 ReadChartSubStream( rStrm );
1735 // set frame format from OBJ record, it is used if chart itself is transparent
1736 if( mxChart )
1737 mxChart->UpdateObjFrame( maLineData, maFillData );
1740 void XclImpChartObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 /*nSubRecSize*/ )
1742 // read the following chart substream
1743 if( nSubRecId == EXC_ID_OBJEND )
1745 // enable CONTINUE handling for the entire chart substream
1746 rStrm.ResetRecord( true );
1747 ReadChartSubStream( rStrm );
1748 /* disable CONTINUE handling again to be able to read
1749 following CONTINUE records as MSODRAWING records. */
1750 rStrm.ResetRecord( false );
1754 std::size_t XclImpChartObj::DoGetProgressSize() const
1756 return mxChart ? mxChart->GetProgressSize() : 1;
1759 rtl::Reference<SdrObject> XclImpChartObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1761 rtl::Reference<SdrObject> xSdrObj;
1762 ScDocShell* pDocShell = GetDocShell();
1763 if( rDffConv.SupportsOleObjects() && SvtModuleOptions().IsChartInstalled() && pDocShell && mxChart && !mxChart->IsPivotChart() )
1765 // create embedded chart object
1766 OUString aEmbObjName;
1767 OUString sBaseURL(GetRoot().GetMedium().GetBaseURL());
1768 Reference< XEmbeddedObject > xEmbObj = pDocShell->GetEmbeddedObjectContainer().
1769 CreateEmbeddedObject( SvGlobalName( SO3_SCH_CLASSID ).GetByteSequence(), aEmbObjName, &sBaseURL );
1771 if (!xEmbObj)
1772 return xSdrObj;
1774 /* Set the size to the embedded object, this prevents that font sizes
1775 of text objects are changed in the chart when the object is
1776 inserted into the draw page. */
1777 sal_Int64 nAspect = css::embed::Aspects::MSOLE_CONTENT;
1778 MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xEmbObj->getMapUnit( nAspect ) );
1779 Size aSize( OutputDevice::LogicToLogic( rAnchorRect.GetSize(), MapMode( MapUnit::Map100thMM ), MapMode( aUnit ) ) );
1780 css::awt::Size aAwtSize( aSize.Width(), aSize.Height() );
1781 xEmbObj->setVisualAreaSize( nAspect, aAwtSize );
1783 // #i121334# This call will change the chart's default background fill from white to transparent.
1784 // Add here again if this is wanted (see task description for details)
1785 // ChartHelper::AdaptDefaultsForChart( xEmbObj );
1787 // create the container OLE object
1788 xSdrObj =
1789 new SdrOle2Obj(
1790 *GetDoc().GetDrawLayer(),
1791 svt::EmbeddedObjectRef(xEmbObj, nAspect),
1792 aEmbObjName,
1793 rAnchorRect);
1796 return xSdrObj;
1799 void XclImpChartObj::DoPostProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const
1801 const SdrOle2Obj* pSdrOleObj = dynamic_cast< const SdrOle2Obj* >( &rSdrObj );
1802 if( !(mxChart && pSdrOleObj) )
1803 return;
1805 const Reference< XEmbeddedObject >& xEmbObj = pSdrOleObj->GetObjRef();
1806 if( xEmbObj.is() && ::svt::EmbeddedObjectRef::TryRunningState( xEmbObj ) ) try
1808 Reference< XEmbedPersist > xPersist( xEmbObj, UNO_QUERY_THROW );
1809 Reference< XModel > xModel( xEmbObj->getComponent(), UNO_QUERY_THROW );
1810 mxChart->Convert( xModel, rDffConv, xPersist->getEntryName(), rSdrObj.GetLogicRect() );
1812 catch( const Exception& )
1817 void XclImpChartObj::FinalizeTabChart()
1819 /* #i44077# Calculate and store DFF anchor for sheet charts.
1820 Needed to get used area if this chart is inserted as OLE object. */
1821 OSL_ENSURE( mbOwnTab, "XclImpChartObj::FinalizeTabChart - not allowed for embedded chart objects" );
1823 // set uninitialized page to landscape
1824 if( !GetPageSettings().GetPageData().mbValid )
1825 GetPageSettings().SetPaperSize( EXC_PAPERSIZE_DEFAULT, false );
1827 // calculate size of the chart object
1828 const XclPageData& rPageData = GetPageSettings().GetPageData();
1829 Size aPaperSize = rPageData.GetScPaperSize();
1831 tools::Long nWidth = XclTools::GetHmmFromTwips( aPaperSize.Width() );
1832 tools::Long nHeight = XclTools::GetHmmFromTwips( aPaperSize.Height() );
1834 // subtract page margins, give some more extra space
1835 nWidth -= o3tl::saturating_add(XclTools::GetHmmFromInch(rPageData.mfLeftMargin + rPageData.mfRightMargin), static_cast<sal_Int32>(2000));
1836 nHeight -= o3tl::saturating_add(XclTools::GetHmmFromInch(rPageData.mfTopMargin + rPageData.mfBottomMargin), static_cast<sal_Int32>(1000));
1838 // print column/row headers?
1839 if( rPageData.mbPrintHeadings )
1841 nWidth -= 2000;
1842 nHeight -= 1000;
1845 // create the object anchor
1846 XclObjAnchor aAnchor;
1847 aAnchor.SetRect( GetRoot(), GetCurrScTab(), tools::Rectangle( 1000, 500, nWidth, nHeight ), MapUnit::Map100thMM );
1848 SetAnchor( aAnchor );
1851 XclImpNoteObj::XclImpNoteObj( const XclImpRoot& rRoot ) :
1852 XclImpTextObj( rRoot ),
1853 maScPos( ScAddress::INITIALIZE_INVALID ),
1854 mnNoteFlags( 0 )
1856 SetSimpleMacro( false );
1857 // caption object will be created manually
1858 SetInsertSdrObj( false );
1861 void XclImpNoteObj::SetNoteData( const ScAddress& rScPos, sal_uInt16 nNoteFlags )
1863 maScPos = rScPos;
1864 mnNoteFlags = nNoteFlags;
1867 void XclImpNoteObj::DoPreProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const
1869 // create formatted text
1870 XclImpTextObj::DoPreProcessSdrObj( rDffConv, rSdrObj );
1871 OutlinerParaObject* pOutlinerObj = rSdrObj.GetOutlinerParaObject();
1872 if( maScPos.IsValid() && pOutlinerObj )
1874 // create cell note with all data from drawing object
1875 ScNoteUtil::CreateNoteFromObjectData(
1876 GetDoc(), maScPos,
1877 rSdrObj.GetMergedItemSet(),
1878 OUString(), *pOutlinerObj,
1879 rSdrObj.GetLogicRect(),
1880 ::get_flag( mnNoteFlags, EXC_NOTE_VISIBLE ) );
1884 XclImpControlHelper::XclImpControlHelper( const XclImpRoot& rRoot, XclCtrlBindMode eBindMode ) :
1885 mrRoot( rRoot ),
1886 meBindMode( eBindMode )
1890 XclImpControlHelper::~XclImpControlHelper()
1894 rtl::Reference<SdrObject> XclImpControlHelper::CreateSdrObjectFromShape(
1895 const Reference< XShape >& rxShape, const tools::Rectangle& rAnchorRect ) const
1897 mxShape = rxShape;
1898 rtl::Reference<SdrObject> xSdrObj( SdrObject::getSdrObjectFromXShape( rxShape ) );
1899 if( xSdrObj )
1901 xSdrObj->NbcSetSnapRect( rAnchorRect );
1902 // #i30543# insert into control layer
1903 xSdrObj->NbcSetLayer( SC_LAYER_CONTROLS );
1905 return xSdrObj;
1908 void XclImpControlHelper::ApplySheetLinkProps() const
1911 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( mxShape );
1912 if( !xCtrlModel.is() )
1913 return;
1915 // sheet links
1916 ScDocShell* pDocShell = mrRoot.GetDocShell();
1917 if(!pDocShell)
1918 return;
1920 ScModelObj* pModelObj = pDocShell->GetModel();
1921 if( !pModelObj )
1922 return;
1924 // cell link
1925 if( mxCellLink ) try
1927 Reference< XBindableValue > xBindable( xCtrlModel, UNO_QUERY_THROW );
1929 // create argument sequence for createInstanceWithArguments()
1930 CellAddress aApiAddress;
1931 ScUnoConversion::FillApiAddress( aApiAddress, *mxCellLink );
1933 NamedValue aValue;
1934 aValue.Name = SC_UNONAME_BOUNDCELL;
1935 aValue.Value <<= aApiAddress;
1937 Sequence< Any > aArgs{ Any(aValue) };
1939 // create the CellValueBinding instance and set at the control model
1940 OUString aServiceName;
1941 switch( meBindMode )
1943 case EXC_CTRL_BINDCONTENT: aServiceName = SC_SERVICENAME_VALBIND; break;
1944 case EXC_CTRL_BINDPOSITION: aServiceName = SC_SERVICENAME_LISTCELLBIND; break;
1946 Reference< XValueBinding > xBinding(
1947 pModelObj->createInstanceWithArguments( aServiceName, aArgs ), UNO_QUERY_THROW );
1948 xBindable->setValueBinding( xBinding );
1950 catch( const Exception& )
1954 // source range
1955 if( !mxSrcRange )
1956 return;
1960 Reference< XListEntrySink > xEntrySink( xCtrlModel, UNO_QUERY_THROW );
1962 // create argument sequence for createInstanceWithArguments()
1963 CellRangeAddress aApiRange;
1964 ScUnoConversion::FillApiRange( aApiRange, *mxSrcRange );
1966 NamedValue aValue;
1967 aValue.Name = SC_UNONAME_CELLRANGE;
1968 aValue.Value <<= aApiRange;
1970 Sequence< Any > aArgs{ Any(aValue) };
1972 // create the EntrySource instance and set at the control model
1973 Reference< XListEntrySource > xEntrySource( pModelObj->createInstanceWithArguments(
1974 SC_SERVICENAME_LISTSOURCE, aArgs ), UNO_QUERY_THROW );
1975 xEntrySink->setListEntrySource( xEntrySource );
1977 catch( const Exception& )
1982 void XclImpControlHelper::ProcessControl( const XclImpDrawObjBase& rDrawObj ) const
1984 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( mxShape );
1985 if( !xCtrlModel.is() )
1986 return;
1988 ApplySheetLinkProps();
1990 ScfPropertySet aPropSet( xCtrlModel );
1992 // #i51348# set object name at control model
1993 aPropSet.SetStringProperty( u"Name"_ustr, rDrawObj.GetObjName() );
1995 // control visible and printable?
1996 aPropSet.SetBoolProperty( u"EnableVisible"_ustr, rDrawObj.IsVisible() );
1997 aPropSet.SetBoolProperty( u"Printable"_ustr, rDrawObj.IsPrintable() );
1999 // virtual call for type specific processing
2000 DoProcessControl( aPropSet );
2003 void XclImpControlHelper::ReadCellLinkFormula( XclImpStream& rStrm, bool bWithBoundSize )
2005 ScRangeList aScRanges;
2006 ReadRangeList( aScRanges, rStrm, bWithBoundSize );
2007 // Use first cell of first range
2008 if ( !aScRanges.empty() )
2010 const ScRange & rScRange = aScRanges.front();
2011 mxCellLink = std::make_shared<ScAddress>( rScRange.aStart );
2015 void XclImpControlHelper::ReadSourceRangeFormula( XclImpStream& rStrm, bool bWithBoundSize )
2017 ScRangeList aScRanges;
2018 ReadRangeList( aScRanges, rStrm, bWithBoundSize );
2019 // Use first range
2020 if ( !aScRanges.empty() )
2022 const ScRange & rScRange = aScRanges.front();
2023 mxSrcRange = std::make_shared<ScRange>( rScRange );
2027 void XclImpControlHelper::DoProcessControl( ScfPropertySet& ) const
2031 void XclImpControlHelper::ReadRangeList( ScRangeList& rScRanges, XclImpStream& rStrm )
2033 XclTokenArray aXclTokArr;
2034 sal_uInt16 nSize = XclTokenArray::ReadSize(rStrm);
2035 rStrm.Ignore( 4 );
2036 aXclTokArr.ReadArray(nSize, rStrm);
2037 mrRoot.GetFormulaCompiler().CreateRangeList( rScRanges, EXC_FMLATYPE_CONTROL, aXclTokArr, rStrm );
2040 void XclImpControlHelper::ReadRangeList( ScRangeList& rScRanges, XclImpStream& rStrm, bool bWithBoundSize )
2042 if( bWithBoundSize )
2044 sal_uInt16 nSize;
2045 nSize = rStrm.ReaduInt16();
2046 if( nSize > 0 )
2048 rStrm.PushPosition();
2049 ReadRangeList( rScRanges, rStrm );
2050 rStrm.PopPosition();
2051 rStrm.Ignore( nSize );
2054 else
2056 ReadRangeList( rScRanges, rStrm );
2060 XclImpTbxObjBase::XclImpTbxObjBase( const XclImpRoot& rRoot ) :
2061 XclImpTextObj( rRoot ),
2062 XclImpControlHelper( rRoot, EXC_CTRL_BINDPOSITION )
2064 SetSimpleMacro( false );
2065 SetCustomDffObj( true );
2068 namespace {
2070 void lclExtractColor( sal_uInt8& rnColorIdx, const DffPropSet& rDffPropSet, sal_uInt32 nPropId )
2072 if( rDffPropSet.IsProperty( nPropId ) )
2074 sal_uInt32 nColor = rDffPropSet.GetPropertyValue( nPropId, 0 );
2075 if( (nColor & 0xFF000000) == 0x08000000 )
2076 rnColorIdx = ::extract_value< sal_uInt8 >( nColor, 0, 8 );
2080 } // namespace
2082 void XclImpTbxObjBase::SetDffProperties( const DffPropSet& rDffPropSet )
2084 maFillData.mnPattern = rDffPropSet.GetPropertyBool( DFF_Prop_fFilled ) ? EXC_PATT_SOLID : EXC_PATT_NONE;
2085 lclExtractColor( maFillData.mnBackColorIdx, rDffPropSet, DFF_Prop_fillBackColor );
2086 lclExtractColor( maFillData.mnPattColorIdx, rDffPropSet, DFF_Prop_fillColor );
2087 ::set_flag( maFillData.mnAuto, EXC_OBJ_LINE_AUTO, false );
2089 maLineData.mnStyle = rDffPropSet.GetPropertyBool( DFF_Prop_fLine ) ? EXC_OBJ_LINE_SOLID : EXC_OBJ_LINE_NONE;
2090 lclExtractColor( maLineData.mnColorIdx, rDffPropSet, DFF_Prop_lineColor );
2091 ::set_flag( maLineData.mnAuto, EXC_OBJ_FILL_AUTO, false );
2094 void XclImpControlHelper::SetStringProperty(const OUString& sName, const OUString& sVal)
2096 Reference<XControlModel> xCtrlModel = XclControlHelper::GetControlModel(mxShape);
2097 if (!xCtrlModel.is())
2098 return;
2100 ScfPropertySet aProps(xCtrlModel);
2101 aProps.SetStringProperty(sName, sVal);
2104 bool XclImpTbxObjBase::FillMacroDescriptor( ScriptEventDescriptor& rDescriptor ) const
2106 return XclControlHelper::FillMacroDescriptor( rDescriptor, DoGetEventType(), GetMacroName(), GetDocShell() );
2109 void XclImpTbxObjBase::ConvertFont( ScfPropertySet& rPropSet ) const
2111 if( maTextData.mxString )
2113 const XclFormatRunVec& rFormatRuns = maTextData.mxString->GetFormats();
2114 if( rFormatRuns.empty() )
2115 GetFontBuffer().WriteDefaultCtrlFontProperties( rPropSet );
2116 else
2117 GetFontBuffer().WriteFontProperties( rPropSet, EXC_FONTPROPSET_CONTROL, rFormatRuns.front().mnFontIdx );
2121 void XclImpTbxObjBase::ConvertLabel( ScfPropertySet& rPropSet ) const
2123 if( maTextData.mxString )
2125 OUString aLabel = maTextData.mxString->GetText();
2126 if( maTextData.maData.mnShortcut > 0 )
2128 sal_Int32 nPos = aLabel.indexOf( static_cast< sal_Unicode >( maTextData.maData.mnShortcut ) );
2129 if( nPos != -1 )
2130 aLabel = aLabel.replaceAt( nPos, 0, u"~" );
2132 rPropSet.SetStringProperty( u"Label"_ustr, aLabel );
2134 //Excel Alt text <==> Aoo description
2135 //For TBX control, if user does not operate alt text, alt text will be set label text as default value in Excel.
2136 //In this case, DFF_Prop_wzDescription will not be set in excel file.
2137 //So In the end of SvxMSDffManager::ImportShape, description will not be set. But actually in excel,
2138 //the alt text is the label value. So here set description as label text first which is called before ImportShape.
2139 Reference< css::beans::XPropertySet > xPropset( mxShape, UNO_QUERY );
2140 try{
2141 if(xPropset.is())
2142 xPropset->setPropertyValue( u"Description"_ustr, Any(aLabel) );
2143 }catch( ... )
2145 SAL_WARN("sc.filter", "Can't set a default text for TBX Control ");
2148 ConvertFont( rPropSet );
2151 rtl::Reference<SdrObject> XclImpTbxObjBase::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
2153 rtl::Reference<SdrObject> xSdrObj( rDffConv.CreateSdrObject( *this, rAnchorRect ) );
2154 rDffConv.Progress();
2155 return xSdrObj;
2158 void XclImpTbxObjBase::DoPreProcessSdrObj( XclImpDffConverter& /*rDffConv*/, SdrObject& /*rSdrObj*/ ) const
2160 // do not call DoPreProcessSdrObj() from base class (to skip text processing)
2161 ProcessControl( *this );
2164 XclImpButtonObj::XclImpButtonObj( const XclImpRoot& rRoot ) :
2165 XclImpTbxObjBase( rRoot )
2169 void XclImpButtonObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2171 // label and text formatting
2172 ConvertLabel( rPropSet );
2174 /* Horizontal text alignment. For unknown reason, the property type is a
2175 simple sal_Int16 and not a com.sun.star.style.HorizontalAlignment. */
2176 sal_Int16 nHorAlign = 1;
2177 switch( maTextData.maData.GetHorAlign() )
2179 case EXC_OBJ_HOR_LEFT: nHorAlign = 0; break;
2180 case EXC_OBJ_HOR_CENTER: nHorAlign = 1; break;
2181 case EXC_OBJ_HOR_RIGHT: nHorAlign = 2; break;
2183 rPropSet.SetProperty( u"Align"_ustr, nHorAlign );
2185 // vertical text alignment
2186 namespace csss = css::style;
2187 csss::VerticalAlignment eVerAlign = csss::VerticalAlignment_MIDDLE;
2188 switch( maTextData.maData.GetVerAlign() )
2190 case EXC_OBJ_VER_TOP: eVerAlign = csss::VerticalAlignment_TOP; break;
2191 case EXC_OBJ_VER_CENTER: eVerAlign = csss::VerticalAlignment_MIDDLE; break;
2192 case EXC_OBJ_VER_BOTTOM: eVerAlign = csss::VerticalAlignment_BOTTOM; break;
2194 rPropSet.SetProperty( u"VerticalAlign"_ustr, eVerAlign );
2196 // always wrap text automatically
2197 rPropSet.SetBoolProperty( u"MultiLine"_ustr, true );
2199 // default button
2200 bool bDefButton = ::get_flag( maTextData.maData.mnButtonFlags, EXC_OBJ_BUTTON_DEFAULT );
2201 rPropSet.SetBoolProperty( u"DefaultButton"_ustr, bDefButton );
2203 // button type (flags cannot be combined in OOo)
2204 namespace cssa = css::awt;
2205 cssa::PushButtonType eButtonType = cssa::PushButtonType_STANDARD;
2206 if( ::get_flag( maTextData.maData.mnButtonFlags, EXC_OBJ_BUTTON_CLOSE ) )
2207 eButtonType = cssa::PushButtonType_OK;
2208 else if( ::get_flag( maTextData.maData.mnButtonFlags, EXC_OBJ_BUTTON_CANCEL ) )
2209 eButtonType = cssa::PushButtonType_CANCEL;
2210 else if( ::get_flag( maTextData.maData.mnButtonFlags, EXC_OBJ_BUTTON_HELP ) )
2211 eButtonType = cssa::PushButtonType_HELP;
2212 // property type is short, not enum
2213 rPropSet.SetProperty( u"PushButtonType"_ustr, sal_Int16( eButtonType ) );
2216 OUString XclImpButtonObj::DoGetServiceName() const
2218 return u"com.sun.star.form.component.CommandButton"_ustr;
2221 XclTbxEventType XclImpButtonObj::DoGetEventType() const
2223 return EXC_TBX_EVENT_ACTION;
2226 XclImpCheckBoxObj::XclImpCheckBoxObj( const XclImpRoot& rRoot ) :
2227 XclImpTbxObjBase( rRoot ),
2228 mnState( EXC_OBJ_CHECKBOX_UNCHECKED ),
2229 mnCheckBoxFlags( 0 )
2233 void XclImpCheckBoxObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2235 ReadFrameData( rStrm );
2236 rStrm.Ignore( 10 );
2237 maTextData.maData.mnFlags = rStrm.ReaduInt16();
2238 rStrm.Ignore( 20 );
2239 ReadName5( rStrm, nNameLen );
2240 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2241 ReadCellLinkFormula( rStrm, true );
2242 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2243 maTextData.ReadByteString( rStrm );
2244 mnState = rStrm.ReaduInt16();
2245 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2246 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16();
2247 mnCheckBoxFlags = rStrm.ReaduInt16();
2250 void XclImpCheckBoxObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2252 switch( nSubRecId )
2254 case EXC_ID_OBJCBLS:
2255 // do not read EXC_ID_OBJCBLSDATA, not written by OOo Excel export
2256 mnState = rStrm.ReaduInt16();
2257 rStrm.Ignore( 4 );
2258 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2259 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16();
2260 mnCheckBoxFlags = rStrm.ReaduInt16();
2261 break;
2262 case EXC_ID_OBJCBLSFMLA:
2263 ReadCellLinkFormula( rStrm, false );
2264 break;
2265 default:
2266 XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2270 void XclImpCheckBoxObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2272 // label and text formatting
2273 ConvertLabel( rPropSet );
2275 // state
2276 bool bSupportsTristate = GetObjType() == EXC_OBJTYPE_CHECKBOX;
2277 sal_Int16 nApiState = 0;
2278 switch( mnState )
2280 case EXC_OBJ_CHECKBOX_UNCHECKED: nApiState = 0; break;
2281 case EXC_OBJ_CHECKBOX_CHECKED: nApiState = 1; break;
2282 case EXC_OBJ_CHECKBOX_TRISTATE: nApiState = bSupportsTristate ? 2 : 1; break;
2284 if( bSupportsTristate )
2285 rPropSet.SetBoolProperty( u"TriState"_ustr, nApiState == 2 );
2286 rPropSet.SetProperty( u"DefaultState"_ustr, nApiState );
2288 // box style
2289 namespace AwtVisualEffect = css::awt::VisualEffect;
2290 sal_Int16 nEffect = ::get_flagvalue( mnCheckBoxFlags, EXC_OBJ_CHECKBOX_FLAT, AwtVisualEffect::FLAT, AwtVisualEffect::LOOK3D );
2291 rPropSet.SetProperty( u"VisualEffect"_ustr, nEffect );
2293 // do not wrap text automatically
2294 rPropSet.SetBoolProperty( u"MultiLine"_ustr, false );
2296 // #i40279# always centered vertically
2297 namespace csss = css::style;
2298 rPropSet.SetProperty( u"VerticalAlign"_ustr, csss::VerticalAlignment_MIDDLE );
2300 // background color
2301 if( maFillData.IsFilled() )
2303 sal_Int32 nColor = static_cast< sal_Int32 >( GetSolidFillColor( maFillData ) );
2304 rPropSet.SetProperty( u"BackgroundColor"_ustr, nColor );
2308 OUString XclImpCheckBoxObj::DoGetServiceName() const
2310 return u"com.sun.star.form.component.CheckBox"_ustr;
2313 XclTbxEventType XclImpCheckBoxObj::DoGetEventType() const
2315 return EXC_TBX_EVENT_ACTION;
2318 XclImpOptionButtonObj::XclImpOptionButtonObj( const XclImpRoot& rRoot ) :
2319 XclImpCheckBoxObj( rRoot ),
2320 mnNextInGroup( 0 ),
2321 mnFirstInGroup( 1 )
2325 void XclImpOptionButtonObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2327 ReadFrameData( rStrm );
2328 rStrm.Ignore( 10 );
2329 maTextData.maData.mnFlags = rStrm.ReaduInt16();
2330 rStrm.Ignore( 32 );
2331 ReadName5( rStrm, nNameLen );
2332 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2333 ReadCellLinkFormula( rStrm, true );
2334 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2335 maTextData.ReadByteString( rStrm );
2336 mnState = rStrm.ReaduInt16();
2337 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2338 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16();
2339 mnCheckBoxFlags = rStrm.ReaduInt16();
2340 mnNextInGroup = rStrm.ReaduInt16();
2341 mnFirstInGroup = rStrm.ReaduInt16();
2344 void XclImpOptionButtonObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2346 switch( nSubRecId )
2348 case EXC_ID_OBJRBODATA:
2349 mnNextInGroup = rStrm.ReaduInt16();
2350 mnFirstInGroup = rStrm.ReaduInt16();
2351 break;
2352 default:
2353 XclImpCheckBoxObj::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2357 void XclImpOptionButtonObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2359 XclImpCheckBoxObj::DoProcessControl( rPropSet );
2360 // TODO: grouping
2361 XclImpOptionButtonObj* pTbxObj = dynamic_cast< XclImpOptionButtonObj* >( GetObjectManager().GetSheetDrawing( GetTab() ).FindDrawObj( mnNextInGroup ).get() );
2362 if ( pTbxObj && pTbxObj->mnFirstInGroup )
2364 // Group has terminated
2365 // traverse each RadioButton in group and
2366 // a) apply the groupname
2367 // b) propagate the linked cell from the lead radiobutton
2368 // c) apply the correct Ref value
2369 XclImpOptionButtonObj* pLeader = pTbxObj;
2371 sal_Int32 nRefVal = 1;
2375 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( pTbxObj->mxShape );
2376 if ( xCtrlModel.is() )
2378 ScfPropertySet aProps( xCtrlModel );
2379 OUString sGroupName = OUString::number( pLeader->GetDffShapeId() );
2381 aProps.SetStringProperty( u"GroupName"_ustr, sGroupName );
2382 aProps.SetStringProperty( u"RefValue"_ustr, OUString::number( nRefVal++ ) );
2383 if ( pLeader->HasCellLink() && !pTbxObj->HasCellLink() )
2385 // propagate cell link info
2386 pTbxObj->mxCellLink = std::make_shared<ScAddress>( *pLeader->mxCellLink );
2387 pTbxObj->ApplySheetLinkProps();
2389 pTbxObj = dynamic_cast< XclImpOptionButtonObj* >( GetObjectManager().GetSheetDrawing( GetTab() ).FindDrawObj( pTbxObj->mnNextInGroup ).get() );
2391 else
2392 pTbxObj = nullptr;
2393 } while ( pTbxObj && ( pTbxObj->mnFirstInGroup != 1 ) );
2395 else
2397 // not the leader? try and find it
2401 OUString XclImpOptionButtonObj::DoGetServiceName() const
2403 return u"com.sun.star.form.component.RadioButton"_ustr;
2406 XclTbxEventType XclImpOptionButtonObj::DoGetEventType() const
2408 return EXC_TBX_EVENT_ACTION;
2411 bool XclImpOptionButtonObj::IsInGroup() const
2413 return mnNextInGroup;
2416 XclImpLabelObj::XclImpLabelObj( const XclImpRoot& rRoot ) :
2417 XclImpTbxObjBase( rRoot )
2421 void XclImpLabelObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2423 // label and text formatting
2424 ConvertLabel( rPropSet );
2426 // text alignment (always top/left aligned)
2427 rPropSet.SetProperty( u"Align"_ustr, sal_Int16( 0 ) );
2428 namespace csss = css::style;
2429 rPropSet.SetProperty( u"VerticalAlign"_ustr, csss::VerticalAlignment_TOP );
2431 // always wrap text automatically
2432 rPropSet.SetBoolProperty( u"MultiLine"_ustr, true );
2435 OUString XclImpLabelObj::DoGetServiceName() const
2437 return u"com.sun.star.form.component.FixedText"_ustr;
2440 XclTbxEventType XclImpLabelObj::DoGetEventType() const
2442 return EXC_TBX_EVENT_MOUSE;
2445 XclImpGroupBoxObj::XclImpGroupBoxObj( const XclImpRoot& rRoot ) :
2446 XclImpTbxObjBase( rRoot ),
2447 mnGroupBoxFlags( 0 )
2451 void XclImpGroupBoxObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2453 ReadFrameData( rStrm );
2454 rStrm.Ignore( 10 );
2455 maTextData.maData.mnFlags = rStrm.ReaduInt16();
2456 rStrm.Ignore( 26 );
2457 ReadName5( rStrm, nNameLen );
2458 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2459 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2460 maTextData.ReadByteString( rStrm );
2461 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2462 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16( );
2463 mnGroupBoxFlags = rStrm.ReaduInt16();
2466 void XclImpGroupBoxObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2468 switch( nSubRecId )
2470 case EXC_ID_OBJGBODATA:
2471 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2472 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16();
2473 mnGroupBoxFlags = rStrm.ReaduInt16();
2474 break;
2475 default:
2476 XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2480 void XclImpGroupBoxObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2482 // label and text formatting
2483 ConvertLabel( rPropSet );
2486 OUString XclImpGroupBoxObj::DoGetServiceName() const
2488 return u"com.sun.star.form.component.GroupBox"_ustr;
2491 XclTbxEventType XclImpGroupBoxObj::DoGetEventType() const
2493 return EXC_TBX_EVENT_MOUSE;
2496 XclImpDialogObj::XclImpDialogObj( const XclImpRoot& rRoot ) :
2497 XclImpTbxObjBase( rRoot )
2501 void XclImpDialogObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2503 // label and text formatting
2504 ConvertLabel( rPropSet );
2507 OUString XclImpDialogObj::DoGetServiceName() const
2509 // dialog frame faked by a groupbox
2510 return u"com.sun.star.form.component.GroupBox"_ustr;
2513 XclTbxEventType XclImpDialogObj::DoGetEventType() const
2515 return EXC_TBX_EVENT_MOUSE;
2518 XclImpEditObj::XclImpEditObj( const XclImpRoot& rRoot ) :
2519 XclImpTbxObjBase( rRoot ),
2520 mnContentType( EXC_OBJ_EDIT_TEXT ),
2521 mnMultiLine( 0 ),
2522 mnScrollBar( 0 ),
2523 mnListBoxObjId( 0 )
2527 bool XclImpEditObj::IsNumeric() const
2529 return (mnContentType == EXC_OBJ_EDIT_INTEGER) || (mnContentType == EXC_OBJ_EDIT_DOUBLE);
2532 void XclImpEditObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2534 ReadFrameData( rStrm );
2535 rStrm.Ignore( 10 );
2536 maTextData.maData.mnFlags = rStrm.ReaduInt16();
2537 rStrm.Ignore( 14 );
2538 ReadName5( rStrm, nNameLen );
2539 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2540 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2541 maTextData.ReadByteString( rStrm );
2542 mnContentType = rStrm.ReaduInt16();
2543 mnMultiLine = rStrm.ReaduInt16();
2544 mnScrollBar = rStrm.ReaduInt16();
2545 mnListBoxObjId = rStrm.ReaduInt16();
2548 void XclImpEditObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2550 switch( nSubRecId )
2552 case EXC_ID_OBJEDODATA:
2553 mnContentType = rStrm.ReaduInt16();
2554 mnMultiLine = rStrm.ReaduInt16();
2555 mnScrollBar = rStrm.ReaduInt16();
2556 mnListBoxObjId = rStrm.ReaduInt16();
2557 break;
2558 default:
2559 XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2563 void XclImpEditObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2565 if( maTextData.mxString )
2567 OUString aText = maTextData.mxString->GetText();
2568 if( IsNumeric() )
2570 // TODO: OUString::toDouble() does not handle local decimal separator
2571 rPropSet.SetProperty( u"DefaultValue"_ustr, aText.toDouble() );
2572 rPropSet.SetBoolProperty( u"Spin"_ustr, mnScrollBar != 0 );
2574 else
2576 rPropSet.SetProperty( u"DefaultText"_ustr, aText );
2577 rPropSet.SetBoolProperty( u"MultiLine"_ustr, mnMultiLine != 0 );
2578 rPropSet.SetBoolProperty( u"VScroll"_ustr, mnScrollBar != 0 );
2581 ConvertFont( rPropSet );
2584 OUString XclImpEditObj::DoGetServiceName() const
2586 return IsNumeric() ?
2587 u"com.sun.star.form.component.NumericField"_ustr :
2588 u"com.sun.star.form.component.TextField"_ustr;
2591 XclTbxEventType XclImpEditObj::DoGetEventType() const
2593 return EXC_TBX_EVENT_TEXT;
2596 XclImpTbxObjScrollableBase::XclImpTbxObjScrollableBase( const XclImpRoot& rRoot ) :
2597 XclImpTbxObjBase( rRoot ),
2598 mnValue( 0 ),
2599 mnMin( 0 ),
2600 mnMax( 100 ),
2601 mnStep( 1 ),
2602 mnPageStep( 10 ),
2603 mnOrient( 0 ),
2604 mnThumbWidth( 1 ),
2605 mnScrollFlags( 0 )
2609 void XclImpTbxObjScrollableBase::ReadSbs( XclImpStream& rStrm )
2611 rStrm.Ignore( 4 );
2612 mnValue = rStrm.ReaduInt16();
2613 mnMin = rStrm.ReaduInt16();
2614 mnMax = rStrm.ReaduInt16();
2615 mnStep = rStrm.ReaduInt16();
2616 mnPageStep = rStrm.ReaduInt16();
2617 mnOrient = rStrm.ReaduInt16();
2618 mnThumbWidth = rStrm.ReaduInt16();
2619 mnScrollFlags = rStrm.ReaduInt16();
2622 void XclImpTbxObjScrollableBase::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2624 switch( nSubRecId )
2626 case EXC_ID_OBJSBS:
2627 ReadSbs( rStrm );
2628 break;
2629 case EXC_ID_OBJSBSFMLA:
2630 ReadCellLinkFormula( rStrm, false );
2631 break;
2632 default:
2633 XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2637 XclImpSpinButtonObj::XclImpSpinButtonObj( const XclImpRoot& rRoot ) :
2638 XclImpTbxObjScrollableBase( rRoot )
2642 void XclImpSpinButtonObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2644 ReadFrameData( rStrm );
2645 ReadSbs( rStrm );
2646 ReadName5( rStrm, nNameLen );
2647 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2648 ReadCellLinkFormula( rStrm, true );
2651 void XclImpSpinButtonObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2653 // Calc's "Border" property is not the 3D/flat style effect in Excel (#i34712#)
2654 rPropSet.SetProperty( u"Border"_ustr, css::awt::VisualEffect::NONE );
2655 rPropSet.SetProperty< sal_Int32 >( u"DefaultSpinValue"_ustr, mnValue );
2656 rPropSet.SetProperty< sal_Int32 >( u"SpinValueMin"_ustr, mnMin );
2657 rPropSet.SetProperty< sal_Int32 >( u"SpinValueMax"_ustr, mnMax );
2658 rPropSet.SetProperty< sal_Int32 >( u"SpinIncrement"_ustr, mnStep );
2660 // Excel spin buttons always vertical
2661 rPropSet.SetProperty( u"Orientation"_ustr, css::awt::ScrollBarOrientation::VERTICAL );
2664 OUString XclImpSpinButtonObj::DoGetServiceName() const
2666 return u"com.sun.star.form.component.SpinButton"_ustr;
2669 XclTbxEventType XclImpSpinButtonObj::DoGetEventType() const
2671 return EXC_TBX_EVENT_VALUE;
2674 XclImpScrollBarObj::XclImpScrollBarObj( const XclImpRoot& rRoot ) :
2675 XclImpTbxObjScrollableBase( rRoot )
2679 void XclImpScrollBarObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2681 ReadFrameData( rStrm );
2682 ReadSbs( rStrm );
2683 ReadName5( rStrm, nNameLen );
2684 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2685 ReadCellLinkFormula( rStrm, true );
2688 void XclImpScrollBarObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2690 // Calc's "Border" property is not the 3D/flat style effect in Excel (#i34712#)
2691 rPropSet.SetProperty( u"Border"_ustr, css::awt::VisualEffect::NONE );
2692 rPropSet.SetProperty< sal_Int32 >( u"DefaultScrollValue"_ustr, mnValue );
2693 rPropSet.SetProperty< sal_Int32 >( u"ScrollValueMin"_ustr, mnMin );
2694 rPropSet.SetProperty< sal_Int32 >( u"ScrollValueMax"_ustr, mnMax );
2695 rPropSet.SetProperty< sal_Int32 >( u"LineIncrement"_ustr, mnStep );
2696 rPropSet.SetProperty< sal_Int32 >( u"BlockIncrement"_ustr, mnPageStep );
2697 rPropSet.SetProperty( u"VisibleSize"_ustr, ::std::min< sal_Int32 >( mnPageStep, 1 ) );
2699 namespace AwtScrollOrient = css::awt::ScrollBarOrientation;
2700 sal_Int32 nApiOrient = ::get_flagvalue( mnOrient, EXC_OBJ_SCROLLBAR_HOR, AwtScrollOrient::HORIZONTAL, AwtScrollOrient::VERTICAL );
2701 rPropSet.SetProperty( u"Orientation"_ustr, nApiOrient );
2704 OUString XclImpScrollBarObj::DoGetServiceName() const
2706 return u"com.sun.star.form.component.ScrollBar"_ustr;
2709 XclTbxEventType XclImpScrollBarObj::DoGetEventType() const
2711 return EXC_TBX_EVENT_VALUE;
2714 XclImpTbxObjListBase::XclImpTbxObjListBase( const XclImpRoot& rRoot ) :
2715 XclImpTbxObjScrollableBase( rRoot ),
2716 mnEntryCount( 0 ),
2717 mnSelEntry( 0 ),
2718 mnListFlags( 0 ),
2719 mnEditObjId( 0 ),
2720 mbHasDefFontIdx( false )
2724 void XclImpTbxObjListBase::ReadLbsData( XclImpStream& rStrm )
2726 ReadSourceRangeFormula( rStrm, true );
2727 mnEntryCount = rStrm.ReaduInt16();
2728 mnSelEntry = rStrm.ReaduInt16();
2729 mnListFlags = rStrm.ReaduInt16();
2730 mnEditObjId = rStrm.ReaduInt16();
2733 void XclImpTbxObjListBase::SetBoxFormatting( ScfPropertySet& rPropSet ) const
2735 // border style
2736 namespace AwtVisualEffect = css::awt::VisualEffect;
2737 sal_Int16 nApiBorder = ::get_flagvalue( mnListFlags, EXC_OBJ_LISTBOX_FLAT, AwtVisualEffect::FLAT, AwtVisualEffect::LOOK3D );
2738 rPropSet.SetProperty( u"Border"_ustr, nApiBorder );
2740 // font formatting
2741 if( mbHasDefFontIdx )
2742 GetFontBuffer().WriteFontProperties( rPropSet, EXC_FONTPROPSET_CONTROL, maTextData.maData.mnDefFontIdx );
2743 else
2744 GetFontBuffer().WriteDefaultCtrlFontProperties( rPropSet );
2747 XclImpListBoxObj::XclImpListBoxObj( const XclImpRoot& rRoot ) :
2748 XclImpTbxObjListBase( rRoot )
2752 void XclImpListBoxObj::ReadFullLbsData( XclImpStream& rStrm, std::size_t nRecLeft )
2754 std::size_t nRecEnd = rStrm.GetRecPos() + nRecLeft;
2755 ReadLbsData( rStrm );
2756 OSL_ENSURE( (rStrm.GetRecPos() == nRecEnd) || (rStrm.GetRecPos() + mnEntryCount == nRecEnd),
2757 "XclImpListBoxObj::ReadFullLbsData - invalid size of OBJLBSDATA record" );
2758 while (rStrm.IsValid())
2760 if (rStrm.GetRecPos() >= nRecEnd)
2761 break;
2762 maSelection.push_back( rStrm.ReaduInt8() );
2766 void XclImpListBoxObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2768 ReadFrameData( rStrm );
2769 ReadSbs( rStrm );
2770 rStrm.Ignore( 18 );
2771 maTextData.maData.mnDefFontIdx = rStrm.ReaduInt16();
2772 rStrm.Ignore( 4 );
2773 ReadName5( rStrm, nNameLen );
2774 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2775 ReadCellLinkFormula( rStrm, true );
2776 ReadFullLbsData( rStrm, rStrm.GetRecLeft() );
2777 mbHasDefFontIdx = true;
2780 void XclImpListBoxObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2782 switch( nSubRecId )
2784 case EXC_ID_OBJLBSDATA:
2785 ReadFullLbsData( rStrm, nSubRecSize );
2786 break;
2787 default:
2788 XclImpTbxObjListBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2792 void XclImpListBoxObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2794 // listbox formatting
2795 SetBoxFormatting( rPropSet );
2797 // selection type
2798 sal_uInt8 nSelType = ::extract_value< sal_uInt8 >( mnListFlags, 4, 2 );
2799 bool bMultiSel = nSelType != EXC_OBJ_LISTBOX_SINGLE;
2800 rPropSet.SetBoolProperty( u"MultiSelection"_ustr, bMultiSel );
2802 // selection (do not set, if listbox is linked to a cell)
2803 if( HasCellLink() )
2804 return;
2806 ScfInt16Vec aSelVec;
2808 // multi selection: API expects sequence of list entry indexes
2809 if( bMultiSel )
2811 sal_Int16 nIndex = 0;
2812 for( const auto& rItem : maSelection )
2814 if( rItem != 0 )
2815 aSelVec.push_back( nIndex );
2816 ++nIndex;
2819 // single selection: mnSelEntry is one-based, API expects zero-based
2820 else if( mnSelEntry > 0 )
2821 aSelVec.push_back( static_cast< sal_Int16 >( mnSelEntry - 1 ) );
2823 if( !aSelVec.empty() )
2825 Sequence<sal_Int16> aSelSeq(aSelVec.data(), static_cast<sal_Int32>(aSelVec.size()));
2826 rPropSet.SetProperty( u"DefaultSelection"_ustr, aSelSeq );
2830 OUString XclImpListBoxObj::DoGetServiceName() const
2832 return u"com.sun.star.form.component.ListBox"_ustr;
2835 XclTbxEventType XclImpListBoxObj::DoGetEventType() const
2837 return EXC_TBX_EVENT_CHANGE;
2840 XclImpDropDownObj::XclImpDropDownObj( const XclImpRoot& rRoot ) :
2841 XclImpTbxObjListBase( rRoot ),
2842 mnLeft( 0 ),
2843 mnTop( 0 ),
2844 mnRight( 0 ),
2845 mnBottom( 0 ),
2846 mnDropDownFlags( 0 ),
2847 mnLineCount( 0 ),
2848 mnMinWidth( 0 )
2852 sal_uInt16 XclImpDropDownObj::GetDropDownType() const
2854 return ::extract_value< sal_uInt8 >( mnDropDownFlags, 0, 2 );
2857 void XclImpDropDownObj::ReadFullLbsData( XclImpStream& rStrm )
2859 ReadLbsData( rStrm );
2860 mnDropDownFlags = rStrm.ReaduInt16();
2861 mnLineCount = rStrm.ReaduInt16();
2862 mnMinWidth = rStrm.ReaduInt16();
2863 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2864 maTextData.ReadByteString( rStrm );
2865 // dropdowns of auto-filters have 'simple' style, they don't have a text area
2866 if( GetDropDownType() == EXC_OBJ_DROPDOWN_SIMPLE )
2867 SetProcessSdrObj( false );
2870 void XclImpDropDownObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2872 ReadFrameData( rStrm );
2873 ReadSbs( rStrm );
2874 rStrm.Ignore( 18 );
2875 maTextData.maData.mnDefFontIdx = rStrm.ReaduInt16();
2876 rStrm.Ignore( 14 );
2877 mnLeft = rStrm.ReaduInt16();
2878 mnTop = rStrm.ReaduInt16();
2879 mnRight = rStrm.ReaduInt16();
2880 mnBottom = rStrm.ReaduInt16();
2881 rStrm.Ignore( 4 );
2882 ReadName5( rStrm, nNameLen );
2883 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2884 ReadCellLinkFormula( rStrm, true );
2885 ReadFullLbsData( rStrm );
2886 mbHasDefFontIdx = true;
2889 void XclImpDropDownObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2891 switch( nSubRecId )
2893 case EXC_ID_OBJLBSDATA:
2894 ReadFullLbsData( rStrm );
2895 break;
2896 default:
2897 XclImpTbxObjListBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2901 void XclImpDropDownObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2903 // dropdown listbox formatting
2904 SetBoxFormatting( rPropSet );
2905 // enable dropdown button
2906 rPropSet.SetBoolProperty( u"Dropdown"_ustr, true );
2907 // dropdown line count
2908 rPropSet.SetProperty( u"LineCount"_ustr, mnLineCount );
2910 if( GetDropDownType() == EXC_OBJ_DROPDOWN_COMBOBOX )
2912 // text of editable combobox
2913 if( maTextData.mxString )
2914 rPropSet.SetStringProperty( u"DefaultText"_ustr, maTextData.mxString->GetText() );
2916 else
2918 // selection (do not set, if dropdown is linked to a cell)
2919 if( !HasCellLink() && (mnSelEntry > 0) )
2921 Sequence< sal_Int16 > aSelSeq{ o3tl::narrowing<sal_Int16>(mnSelEntry - 1) };
2922 rPropSet.SetProperty( u"DefaultSelection"_ustr, aSelSeq );
2927 OUString XclImpDropDownObj::DoGetServiceName() const
2929 return (GetDropDownType() == EXC_OBJ_DROPDOWN_COMBOBOX) ?
2930 u"com.sun.star.form.component.ComboBox"_ustr :
2931 u"com.sun.star.form.component.ListBox"_ustr;
2934 XclTbxEventType XclImpDropDownObj::DoGetEventType() const
2936 return (GetDropDownType() == EXC_OBJ_DROPDOWN_COMBOBOX) ? EXC_TBX_EVENT_TEXT : EXC_TBX_EVENT_CHANGE;
2939 XclImpPictureObj::XclImpPictureObj( const XclImpRoot& rRoot ) :
2940 XclImpRectObj( rRoot ),
2941 XclImpControlHelper( rRoot, EXC_CTRL_BINDCONTENT ),
2942 mnStorageId( 0 ),
2943 mnCtlsStrmPos( 0 ),
2944 mnCtlsStrmSize( 0 ),
2945 mbEmbedded( false ),
2946 mbLinked( false ),
2947 mbSymbol( false ),
2948 mbControl( false ),
2949 mbUseCtlsStrm( false )
2951 SetAreaObj( true );
2952 SetSimpleMacro( true );
2953 SetCustomDffObj( true );
2956 OUString XclImpPictureObj::GetOleStorageName() const
2958 OUStringBuffer aStrgName;
2959 if( (mbEmbedded || mbLinked) && !mbControl && (mnStorageId > 0) )
2961 aStrgName = mbEmbedded ? std::u16string_view(u"" EXC_STORAGE_OLE_EMBEDDED) : std::u16string_view(u"" EXC_STORAGE_OLE_LINKED);
2962 static const char spcHexChars[] = "0123456789ABCDEF";
2963 for( sal_uInt8 nIndex = 32; nIndex > 0; nIndex -= 4 )
2964 aStrgName.append(OUStringChar( spcHexChars[ ::extract_value< sal_uInt8 >( mnStorageId, nIndex - 4, 4 ) ] ));
2966 return aStrgName.makeStringAndClear();
2969 void XclImpPictureObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
2971 sal_uInt16 nLinkSize;
2972 ReadFrameData( rStrm );
2973 rStrm.Ignore( 6 );
2974 nLinkSize = rStrm.ReaduInt16();
2975 rStrm.Ignore( 2 );
2976 ReadFlags3( rStrm );
2977 ReadMacro3( rStrm, nMacroSize );
2978 ReadPictFmla( rStrm, nLinkSize );
2980 if( (rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord() )
2981 maGraphic = XclImpDrawing::ReadImgData( GetRoot(), rStrm );
2984 void XclImpPictureObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
2986 sal_uInt16 nLinkSize;
2987 ReadFrameData( rStrm );
2988 rStrm.Ignore( 6 );
2989 nLinkSize = rStrm.ReaduInt16();
2990 rStrm.Ignore( 2 );
2991 ReadFlags3( rStrm );
2992 ReadMacro4( rStrm, nMacroSize );
2993 ReadPictFmla( rStrm, nLinkSize );
2995 if( (rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord() )
2996 maGraphic = XclImpDrawing::ReadImgData( GetRoot(), rStrm );
2999 void XclImpPictureObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
3001 sal_uInt16 nLinkSize;
3002 ReadFrameData( rStrm );
3003 rStrm.Ignore( 6 );
3004 nLinkSize = rStrm.ReaduInt16();
3005 rStrm.Ignore( 2 );
3006 ReadFlags3( rStrm );
3007 rStrm.Ignore( 4 );
3008 ReadName5( rStrm, nNameLen );
3009 ReadMacro5( rStrm, nMacroSize );
3010 ReadPictFmla( rStrm, nLinkSize );
3012 if( (rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord() )
3014 // page background is stored as hidden picture with name "__BkgndObj"
3015 if ( IsHidden() && (GetObjName() == "__BkgndObj") )
3016 GetPageSettings().ReadImgData( rStrm );
3017 else
3018 maGraphic = XclImpDrawing::ReadImgData( GetRoot(), rStrm );
3022 void XclImpPictureObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
3024 switch( nSubRecId )
3026 case EXC_ID_OBJFLAGS:
3027 ReadFlags8( rStrm );
3028 break;
3029 case EXC_ID_OBJPICTFMLA:
3030 ReadPictFmla( rStrm, rStrm.ReaduInt16() );
3031 break;
3032 default:
3033 XclImpDrawObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
3037 rtl::Reference<SdrObject> XclImpPictureObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
3039 // try to create an OLE object or form control
3040 rtl::Reference<SdrObject> xSdrObj( rDffConv.CreateSdrObject( *this, rAnchorRect ) );
3042 // insert a graphic replacement for unsupported ole object ( if none already
3043 // exists ) Hmm ok, it's possibly that there has been some imported
3044 // graphic at a base level but unlikely, normally controls have a valid
3045 // preview in the IMGDATA record ( see below )
3046 // It might be possible to push such an imported graphic up to this
3047 // XclImpPictureObj instance but there are so many layers of indirection I
3048 // don't see an easy way. This way at least ensures that we can
3049 // avoid a 'blank' shape that can result from a failed control import
3050 if ( !xSdrObj && IsOcxControl() && maGraphic.GetType() == GraphicType::NONE )
3052 const_cast< XclImpPictureObj* >( this )->maGraphic =
3053 SdrOle2Obj::GetEmptyOLEReplacementGraphic();
3055 // no OLE - create a plain picture from IMGDATA record data
3056 if( !xSdrObj && (maGraphic.GetType() != GraphicType::NONE) )
3058 xSdrObj =
3059 new SdrGrafObj(
3060 *GetDoc().GetDrawLayer(),
3061 maGraphic,
3062 rAnchorRect);
3063 ConvertRectStyle( *xSdrObj );
3066 rDffConv.Progress();
3067 return xSdrObj;
3070 OUString XclImpPictureObj::GetObjName() const
3072 if( IsOcxControl() )
3074 OUString sName( GetObjectManager().GetOleNameOverride( GetTab(), GetObjId() ) );
3075 if (!sName.isEmpty())
3076 return sName;
3078 return XclImpDrawObjBase::GetObjName();
3081 void XclImpPictureObj::DoPreProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const
3083 if( IsOcxControl() )
3085 // do not call XclImpRectObj::DoPreProcessSdrObj(), it would trace missing "printable" feature
3086 ProcessControl( *this );
3088 else if( mbEmbedded || mbLinked )
3090 // trace missing "printable" feature
3091 XclImpRectObj::DoPreProcessSdrObj( rDffConv, rSdrObj );
3093 SfxObjectShell* pDocShell = GetDocShell();
3094 SdrOle2Obj* pOleSdrObj = dynamic_cast< SdrOle2Obj* >( &rSdrObj );
3095 if( pOleSdrObj && pDocShell )
3097 comphelper::EmbeddedObjectContainer& rEmbObjCont = pDocShell->GetEmbeddedObjectContainer();
3098 Reference< XEmbeddedObject > xEmbObj = pOleSdrObj->GetObjRef();
3099 OUString aOldName( pOleSdrObj->GetPersistName() );
3101 /* The object persistence should be already in the storage, but
3102 the object still might not be inserted into the container. */
3103 if( rEmbObjCont.HasEmbeddedObject( aOldName ) )
3105 if( !rEmbObjCont.HasEmbeddedObject( xEmbObj ) )
3106 // filter code is allowed to call the following method
3107 rEmbObjCont.AddEmbeddedObject( xEmbObj, aOldName );
3109 else
3111 /* If the object is still not in container it must be inserted
3112 there, the name must be generated in this case. */
3113 OUString aNewName;
3114 rEmbObjCont.InsertEmbeddedObject( xEmbObj, aNewName );
3115 if( aOldName != aNewName )
3116 // SetPersistName, not SetName
3117 pOleSdrObj->SetPersistName( aNewName );
3123 void XclImpPictureObj::ReadFlags3( XclImpStream& rStrm )
3125 sal_uInt16 nFlags;
3126 nFlags = rStrm.ReaduInt16();
3127 mbSymbol = ::get_flag( nFlags, EXC_OBJ_PIC_SYMBOL );
3130 void XclImpPictureObj::ReadFlags8( XclImpStream& rStrm )
3132 sal_uInt16 nFlags;
3133 nFlags = rStrm.ReaduInt16();
3134 mbSymbol = ::get_flag( nFlags, EXC_OBJ_PIC_SYMBOL );
3135 mbControl = ::get_flag( nFlags, EXC_OBJ_PIC_CONTROL );
3136 mbUseCtlsStrm = ::get_flag( nFlags, EXC_OBJ_PIC_CTLSSTREAM );
3137 OSL_ENSURE( mbControl || !mbUseCtlsStrm, "XclImpPictureObj::ReadFlags8 - CTLS stream for controls only" );
3138 SetProcessSdrObj( mbControl || !mbUseCtlsStrm );
3141 void XclImpPictureObj::ReadPictFmla( XclImpStream& rStrm, sal_uInt16 nLinkSize )
3143 std::size_t nLinkEnd = rStrm.GetRecPos() + nLinkSize;
3144 if( nLinkSize >= 6 )
3146 sal_uInt16 nFmlaSize;
3147 nFmlaSize = rStrm.ReaduInt16();
3148 OSL_ENSURE( nFmlaSize > 0, "XclImpPictureObj::ReadPictFmla - missing link formula" );
3149 // BIFF3/BIFF4 do not support storages, nothing to do here
3150 if( (nFmlaSize > 0) && (GetBiff() >= EXC_BIFF5) )
3152 rStrm.Ignore( 4 );
3153 sal_uInt8 nToken;
3154 nToken = rStrm.ReaduInt8();
3156 // different processing for linked vs. embedded OLE objects
3157 if( nToken == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ) )
3159 mbLinked = true;
3160 switch( GetBiff() )
3162 case EXC_BIFF5:
3164 sal_Int16 nRefIdx;
3165 sal_uInt16 nNameIdx;
3166 nRefIdx = rStrm.ReadInt16();
3167 rStrm.Ignore( 8 );
3168 nNameIdx = rStrm.ReaduInt16();
3169 rStrm.Ignore( 12 );
3170 const ExtName* pExtName = GetOldRoot().pExtNameBuff->GetNameByIndex( nRefIdx, nNameIdx );
3171 if( pExtName && pExtName->IsOLE() )
3172 mnStorageId = pExtName->nStorageId;
3174 break;
3175 case EXC_BIFF8:
3177 sal_uInt16 nXti, nExtName;
3178 nXti = rStrm.ReaduInt16();
3179 nExtName = rStrm.ReaduInt16();
3180 const XclImpExtName* pExtName = GetLinkManager().GetExternName( nXti, nExtName );
3181 if( pExtName && (pExtName->GetType() == xlExtOLE) )
3182 mnStorageId = pExtName->GetStorageId();
3184 break;
3185 default:
3186 DBG_ERROR_BIFF();
3189 else if( nToken == XclTokenArrayHelper::GetTokenId( EXC_TOKID_TBL, EXC_TOKCLASS_NONE ) )
3191 mbEmbedded = true;
3192 OSL_ENSURE( nFmlaSize == 5, "XclImpPictureObj::ReadPictFmla - unexpected formula size" );
3193 rStrm.Ignore( nFmlaSize - 1 ); // token ID already read
3194 if( nFmlaSize & 1 )
3195 rStrm.Ignore( 1 ); // padding byte
3197 // a class name may follow inside the picture link
3198 if( rStrm.GetRecPos() + 2 <= nLinkEnd )
3200 sal_uInt16 nLen = rStrm.ReaduInt16();
3201 if( nLen > 0 )
3202 maClassName = (GetBiff() == EXC_BIFF8) ? rStrm.ReadUniString( nLen ) : rStrm.ReadRawByteString( nLen );
3205 // else: ignore other formulas, e.g. pictures linked to cell ranges
3209 // seek behind picture link data
3210 rStrm.Seek( nLinkEnd );
3212 // read additional data for embedded OLE objects following the picture link
3213 if( IsOcxControl() )
3215 // #i26521# form controls to be ignored
3216 if( maClassName == "Forms.HTML:Hidden.1" )
3218 SetProcessSdrObj( false );
3219 return;
3222 if( rStrm.GetRecLeft() <= 8 ) return;
3224 // position and size of control data in 'Ctls' stream
3225 mnCtlsStrmPos = static_cast< std::size_t >( rStrm.ReaduInt32() );
3226 mnCtlsStrmSize = static_cast< std::size_t >( rStrm.ReaduInt32() );
3228 if( rStrm.GetRecLeft() <= 8 ) return;
3230 // additional string (16-bit characters), e.g. for progress bar control
3231 sal_uInt32 nAddStrSize;
3232 nAddStrSize = rStrm.ReaduInt32();
3233 OSL_ENSURE( rStrm.GetRecLeft() >= nAddStrSize + 4, "XclImpPictureObj::ReadPictFmla - missing data" );
3234 if( rStrm.GetRecLeft() >= nAddStrSize + 4 )
3236 rStrm.Ignore( nAddStrSize );
3237 // cell link and source range
3238 ReadCellLinkFormula( rStrm, true );
3239 ReadSourceRangeFormula( rStrm, true );
3242 else if( mbEmbedded && (rStrm.GetRecLeft() >= 4) )
3244 mnStorageId = rStrm.ReaduInt32();
3248 // DFF stream conversion ======================================================
3250 void XclImpSolverContainer::InsertSdrObjectInfo( SdrObject& rSdrObj, sal_uInt32 nDffShapeId, ShapeFlag nDffFlags )
3252 if( nDffShapeId > 0 )
3254 maSdrInfoMap[ nDffShapeId ].Set( &rSdrObj, nDffFlags );
3255 maSdrObjMap[ &rSdrObj ] = nDffShapeId;
3259 void XclImpSolverContainer::RemoveSdrObjectInfo( SdrObject& rSdrObj )
3261 // remove info of passed object from the maps
3262 XclImpSdrObjMap::iterator aIt = maSdrObjMap.find( &rSdrObj );
3263 if( aIt != maSdrObjMap.end() )
3265 maSdrInfoMap.erase( aIt->second );
3266 maSdrObjMap.erase( aIt );
3269 // remove info of all child objects of a group object
3270 if( SdrObjGroup* pGroupObj = dynamic_cast< SdrObjGroup* >( &rSdrObj ) )
3272 if( SdrObjList* pSubList = pGroupObj->GetSubList() )
3274 // iterate flat over the list because this function already works recursively
3275 SdrObjListIter aObjIt( pSubList, SdrIterMode::Flat );
3276 for( SdrObject* pChildObj = aObjIt.Next(); pChildObj; pChildObj = aObjIt.Next() )
3277 RemoveSdrObjectInfo( *pChildObj );
3282 void XclImpSolverContainer::UpdateConnectorRules()
3284 for (auto const & pRule : aCList)
3286 UpdateConnection( pRule->nShapeA, pRule->pAObj, &pRule->nSpFlagsA );
3287 UpdateConnection( pRule->nShapeB, pRule->pBObj, &pRule->nSpFlagsB );
3288 UpdateConnection( pRule->nShapeC, pRule->pCObj );
3292 void XclImpSolverContainer::RemoveConnectorRules()
3294 aCList.clear();
3295 maSdrInfoMap.clear();
3296 maSdrObjMap.clear();
3299 void XclImpSolverContainer::UpdateConnection( sal_uInt32 nDffShapeId, SdrObject*& rpSdrObj, ShapeFlag* pnDffFlags )
3301 XclImpSdrInfoMap::const_iterator aIt = maSdrInfoMap.find( nDffShapeId );
3302 if( aIt != maSdrInfoMap.end() )
3304 rpSdrObj = aIt->second.mpSdrObj;
3305 if( pnDffFlags )
3306 *pnDffFlags = aIt->second.mnDffFlags;
3310 XclImpSimpleDffConverter::XclImpSimpleDffConverter( const XclImpRoot& rRoot, SvStream& rDffStrm ) :
3311 SvxMSDffManager( rDffStrm, rRoot.GetBasePath(), 0, nullptr, rRoot.GetDoc().GetDrawLayer(), 1440, COL_DEFAULT, nullptr ),
3312 XclImpRoot( rRoot )
3314 SetSvxMSDffSettings( SVXMSDFF_SETTINGS_CROP_BITMAPS | SVXMSDFF_SETTINGS_IMPORT_EXCEL );
3317 XclImpSimpleDffConverter::~XclImpSimpleDffConverter()
3321 bool XclImpSimpleDffConverter::GetColorFromPalette( sal_uInt16 nIndex, Color& rColor ) const
3323 Color nColor = GetPalette().GetColor( nIndex );
3325 if( nColor == COL_AUTO )
3326 return false;
3328 rColor = nColor;
3329 return true;
3332 XclImpDffConverter::XclImpDffConvData::XclImpDffConvData(
3333 XclImpDrawing& rDrawing, SdrModel& rSdrModel, SdrPage& rSdrPage ) :
3334 mrDrawing( rDrawing ),
3335 mrSdrModel( rSdrModel ),
3336 mrSdrPage( rSdrPage ),
3337 mnLastCtrlIndex( -1 ),
3338 mbHasCtrlForm( false )
3342 constexpr OUString gaStdFormName( u"Standard"_ustr ); /// Standard name of control forms.
3344 XclImpDffConverter::XclImpDffConverter( const XclImpRoot& rRoot, SvStream& rDffStrm ) :
3345 XclImpSimpleDffConverter( rRoot, rDffStrm ),
3346 oox::ole::MSConvertOCXControls( rRoot.GetDocShell()->GetModel() ),
3347 mnOleImpFlags( 0 ),
3348 mbNotifyMacroEventRead(false)
3350 if( officecfg::Office::Common::Filter::Microsoft::Import::MathTypeToMath::get() )
3351 mnOleImpFlags |= OLE_MATHTYPE_2_STARMATH;
3352 if( officecfg::Office::Common::Filter::Microsoft::Import::WinWordToWriter::get() )
3353 mnOleImpFlags |= OLE_WINWORD_2_STARWRITER;
3354 if( officecfg::Office::Common::Filter::Microsoft::Import::PowerPointToImpress::get() )
3355 mnOleImpFlags |= OLE_POWERPOINT_2_STARIMPRESS;
3357 // try to open the 'Ctls' storage stream containing OCX control properties
3358 mxCtlsStrm = OpenStream( EXC_STREAM_CTLS );
3360 // default text margin (convert EMU to drawing layer units)
3361 mnDefTextMargin = EXC_OBJ_TEXT_MARGIN;
3362 ScaleEmu( mnDefTextMargin );
3365 XclImpDffConverter::~XclImpDffConverter()
3369 OUString XclImpObjectManager::GetOleNameOverride( SCTAB nTab, sal_uInt16 nObjId )
3371 OUString sOleName;
3372 OUString sCodeName = GetExtDocOptions().GetCodeName( nTab );
3374 if (mxOleCtrlNameOverride.is() && mxOleCtrlNameOverride->hasByName(sCodeName))
3376 Reference< XIndexContainer > xIdToOleName;
3377 mxOleCtrlNameOverride->getByName( sCodeName ) >>= xIdToOleName;
3378 xIdToOleName->getByIndex( nObjId ) >>= sOleName;
3381 return sOleName;
3384 void XclImpDffConverter::StartProgressBar( std::size_t nProgressSize )
3386 mxProgress = std::make_shared<ScfProgressBar>( GetDocShell(), STR_PROGRESS_CALCULATING );
3387 mxProgress->AddSegment( nProgressSize );
3388 mxProgress->Activate();
3391 void XclImpDffConverter::Progress( std::size_t nDelta )
3393 OSL_ENSURE( mxProgress, "XclImpDffConverter::Progress - invalid call, no progress bar" );
3394 mxProgress->Progress( nDelta );
3397 void XclImpDffConverter::InitializeDrawing( XclImpDrawing& rDrawing, SdrModel& rSdrModel, SdrPage& rSdrPage )
3399 XclImpDffConvDataRef xConvData = std::make_shared<XclImpDffConvData>( rDrawing, rSdrModel, rSdrPage );
3400 maDataStack.push_back( xConvData );
3401 SetModel( &xConvData->mrSdrModel, 1440 );
3404 void XclImpDffConverter::ProcessObject( SdrObjList& rObjList, XclImpDrawObjBase& rDrawObj )
3406 if( !rDrawObj.IsProcessSdrObj() )
3407 return;
3409 const XclObjAnchor* pAnchor = rDrawObj.GetAnchor();
3410 if(!pAnchor)
3411 return;
3413 tools::Rectangle aAnchorRect = GetConvData().mrDrawing.CalcAnchorRect( *pAnchor, false );
3414 if( rDrawObj.IsValidSize( aAnchorRect ) )
3416 // CreateSdrObject() recursively creates embedded child objects
3417 rtl::Reference<SdrObject> xSdrObj( rDrawObj.CreateSdrObject( *this, aAnchorRect, false ) );
3418 if( xSdrObj )
3419 rDrawObj.PreProcessSdrObject( *this, *xSdrObj );
3420 // call InsertSdrObject() also, if SdrObject is missing
3421 InsertSdrObject( rObjList, rDrawObj, xSdrObj.get() );
3425 void XclImpDffConverter::ProcessDrawing( const XclImpDrawObjVector& rDrawObjs )
3427 SdrPage& rSdrPage = GetConvData().mrSdrPage;
3428 for( const auto& rxDrawObj : rDrawObjs )
3429 ProcessObject( rSdrPage, *rxDrawObj );
3432 void XclImpDffConverter::ProcessDrawing( SvStream& rDffStrm )
3434 if( rDffStrm.TellEnd() > 0 )
3436 rDffStrm.Seek( STREAM_SEEK_TO_BEGIN );
3437 DffRecordHeader aHeader;
3438 ReadDffRecordHeader( rDffStrm, aHeader );
3439 OSL_ENSURE( aHeader.nRecType == DFF_msofbtDgContainer, "XclImpDffConverter::ProcessDrawing - unexpected record" );
3440 if( aHeader.nRecType == DFF_msofbtDgContainer )
3441 ProcessDgContainer( rDffStrm, aHeader );
3445 void XclImpDffConverter::FinalizeDrawing()
3447 OSL_ENSURE( !maDataStack.empty(), "XclImpDffConverter::FinalizeDrawing - no drawing manager on stack" );
3448 maDataStack.pop_back();
3449 // restore previous model at core DFF converter
3450 if( !maDataStack.empty() )
3451 SetModel( &maDataStack.back()->mrSdrModel, 1440 );
3454 void XclImpDffConverter::NotifyMacroEventRead()
3456 if (mbNotifyMacroEventRead)
3457 return;
3458 comphelper::DocumentInfo::notifyMacroEventRead(mxModel);
3459 mbNotifyMacroEventRead = true;
3462 rtl::Reference<SdrObject> XclImpDffConverter::CreateSdrObject( const XclImpTbxObjBase& rTbxObj, const tools::Rectangle& rAnchorRect )
3464 rtl::Reference<SdrObject> xSdrObj;
3466 OUString aServiceName = rTbxObj.GetServiceName();
3467 if( SupportsOleObjects() && !aServiceName.isEmpty() ) try
3469 // create the form control from scratch
3470 Reference< XFormComponent > xFormComp( ScfApiHelper::CreateInstance( GetDocShell(), aServiceName ), UNO_QUERY_THROW );
3471 // set controls form, needed in virtual function InsertControl()
3472 InitControlForm();
3473 // try to insert the control into the form
3474 css::awt::Size aDummySize;
3475 Reference< XShape > xShape;
3476 XclImpDffConvData& rConvData = GetConvData();
3477 if( rConvData.mxCtrlForm.is() && InsertControl( xFormComp, aDummySize, &xShape, true ) )
3479 xSdrObj = rTbxObj.CreateSdrObjectFromShape( xShape, rAnchorRect );
3480 // try to attach a macro to the control
3481 ScriptEventDescriptor aDescriptor;
3482 if( (rConvData.mnLastCtrlIndex >= 0) && rTbxObj.FillMacroDescriptor( aDescriptor ) )
3484 NotifyMacroEventRead();
3485 Reference< XEventAttacherManager > xEventMgr( rConvData.mxCtrlForm, UNO_QUERY_THROW );
3486 xEventMgr->registerScriptEvent( rConvData.mnLastCtrlIndex, aDescriptor );
3490 catch( const Exception& )
3494 return xSdrObj;
3497 rtl::Reference<SdrObject> XclImpDffConverter::CreateSdrObject( const XclImpPictureObj& rPicObj, const tools::Rectangle& rAnchorRect )
3499 rtl::Reference<SdrObject> xSdrObj;
3501 if( SupportsOleObjects() )
3503 if( rPicObj.IsOcxControl() )
3505 if( mxCtlsStrm.is() ) try
3507 /* set controls form, needed in virtual function InsertControl()
3508 called from ReadOCXExcelKludgeStream() */
3509 InitControlForm();
3511 // read from mxCtlsStrm into xShape, insert the control model into the form
3512 Reference< XShape > xShape;
3513 if( GetConvData().mxCtrlForm.is() )
3515 Reference< XFormComponent > xFComp;
3516 ReadOCXCtlsStream( mxCtlsStrm, xFComp, rPicObj.GetCtlsStreamPos(), rPicObj.GetCtlsStreamSize() );
3517 // recreate the method formerly known as ReadOCXExcelKludgeStream()
3518 if ( xFComp.is() )
3520 css::awt::Size aSz; // not used in import
3521 ScfPropertySet aPropSet( xFComp );
3522 aPropSet.SetStringProperty( u"Name"_ustr, rPicObj.GetObjName() );
3523 InsertControl( xFComp, aSz,&xShape,true);
3524 xSdrObj = rPicObj.CreateSdrObjectFromShape( xShape, rAnchorRect );
3528 catch( const Exception& )
3532 else
3534 SfxObjectShell* pDocShell = GetDocShell();
3535 rtl::Reference<SotStorage> xSrcStrg = GetRootStorage();
3536 OUString aStrgName = rPicObj.GetOleStorageName();
3537 if( pDocShell && xSrcStrg.is() && (!aStrgName.isEmpty()) )
3539 // first try to resolve graphic from DFF storage
3540 Graphic aGraphic;
3541 tools::Rectangle aVisArea;
3542 if( !GetBLIP( GetPropertyValue( DFF_Prop_pib, 0 ), aGraphic, &aVisArea ) )
3544 // if not found, use graphic from object (imported from IMGDATA record)
3545 aGraphic = rPicObj.GetGraphic();
3547 if( aGraphic.GetType() != GraphicType::NONE )
3549 ErrCode nError = ERRCODE_NONE;
3550 namespace cssea = css::embed::Aspects;
3551 sal_Int64 nAspects = rPicObj.IsSymbol() ? cssea::MSOLE_ICON : cssea::MSOLE_CONTENT;
3552 xSdrObj =
3553 CreateSdrOLEFromStorage(
3554 GetConvData().mrSdrModel,
3555 aStrgName,
3556 xSrcStrg,
3557 pDocShell->GetStorage(),
3558 aGraphic,
3559 rAnchorRect,
3560 aVisArea,
3561 nullptr,
3562 nError,
3563 mnOleImpFlags,
3564 nAspects,
3565 GetRoot().GetMedium().GetBaseURL());
3571 return xSdrObj;
3574 bool XclImpDffConverter::SupportsOleObjects() const
3576 return GetConvData().mrDrawing.SupportsOleObjects();
3579 // virtual functions ----------------------------------------------------------
3581 void XclImpDffConverter::ProcessClientAnchor2( SvStream& rDffStrm,
3582 DffRecordHeader& rHeader, DffObjData& rObjData )
3584 // find the OBJ record data related to the processed shape
3585 XclImpDffConvData& rConvData = GetConvData();
3586 XclImpDrawObjBase* pDrawObj = rConvData.mrDrawing.FindDrawObj( rObjData.rSpHd ).get();
3587 if(!pDrawObj)
3588 return;
3590 OSL_ENSURE( rHeader.nRecType == DFF_msofbtClientAnchor, "XclImpDffConverter::ProcessClientAnchor2 - no client anchor record" );
3591 XclObjAnchor aAnchor;
3592 rHeader.SeekToContent( rDffStrm );
3593 sal_uInt8 nFlags(0);
3594 rDffStrm.ReadUChar( nFlags );
3595 rDffStrm.SeekRel( 1 ); // flags
3596 rDffStrm >> aAnchor; // anchor format equal to BIFF5 OBJ records
3598 if (!rDffStrm.good())
3600 SAL_WARN("sc.filter", "ProcessClientAnchor2 short read");
3601 return;
3604 pDrawObj->SetAnchor( aAnchor );
3605 rObjData.aChildAnchor = rConvData.mrDrawing.CalcAnchorRect( aAnchor, true );
3606 rObjData.bChildAnchor = true;
3607 // page anchoring is the best approximation we have if mbMove
3608 // is set
3609 rObjData.bPageAnchor = ( nFlags & 0x1 );
3612 namespace {
3614 struct XclImpDrawObjClientData : public SvxMSDffClientData
3616 const XclImpDrawObjBase* m_pTopLevelObj;
3618 XclImpDrawObjClientData()
3619 : m_pTopLevelObj(nullptr)
3622 virtual void NotifyFreeObj(SdrObject*) override {}
3627 rtl::Reference<SdrObject> XclImpDffConverter::ProcessObj( SvStream& rDffStrm, DffObjData& rDffObjData,
3628 SvxMSDffClientData& rClientData, tools::Rectangle& /*rTextRect*/, SdrObject* pOldSdrObj )
3630 XclImpDffConvData& rConvData = GetConvData();
3632 /* pOldSdrObj passes a generated SdrObject. This function owns this object
3633 and can modify it. The function has either to return it back to caller
3634 or to delete it by itself. */
3635 rtl::Reference<SdrObject> xSdrObj( pOldSdrObj );
3637 // find the OBJ record data related to the processed shape
3638 XclImpDrawObjRef xDrawObj = rConvData.mrDrawing.FindDrawObj( rDffObjData.rSpHd );
3639 const tools::Rectangle& rAnchorRect = rDffObjData.aChildAnchor;
3641 // Do not process the global page group shape
3642 bool bGlobalPageGroup( rDffObjData.nSpFlags & ShapeFlag::Patriarch );
3643 if( !xDrawObj || !xDrawObj->IsProcessSdrObj() || bGlobalPageGroup )
3644 return nullptr; // simply return, xSdrObj will be destroyed
3646 /* Pass pointer to top-level object back to caller. If the processed
3647 object is embedded in a group, the pointer is already set to the
3648 top-level parent object. */
3649 XclImpDrawObjClientData& rDrawObjClientData = static_cast<XclImpDrawObjClientData&>(rClientData);
3650 const bool bIsTopLevel = !rDrawObjClientData.m_pTopLevelObj;
3651 if (bIsTopLevel )
3652 rDrawObjClientData.m_pTopLevelObj = xDrawObj.get();
3654 // connectors don't have to be area objects
3655 if( dynamic_cast< SdrEdgeObj* >( xSdrObj.get() ) )
3656 xDrawObj->SetAreaObj( false );
3658 /* Check for valid size for all objects. Needed to ignore lots of invisible
3659 phantom objects from deleted rows or columns (for performance reasons).
3660 #i30816# Include objects embedded in groups.
3661 #i58780# Ignore group shapes, size is not initialized. */
3662 bool bEmbeddedGroup = !bIsTopLevel && dynamic_cast< SdrObjGroup* >( xSdrObj.get() );
3663 if( !bEmbeddedGroup && !xDrawObj->IsValidSize( rAnchorRect ) )
3664 return nullptr; // simply return, xSdrObj will be destroyed
3666 // set shape information from DFF stream
3667 OUString aObjName = GetPropertyString( DFF_Prop_wzName, rDffStrm );
3668 OUString aHyperlink = ReadHlinkProperty( rDffStrm );
3669 bool bVisible = !GetPropertyBool( DFF_Prop_fHidden );
3670 bool bAutoMargin = GetPropertyBool( DFF_Prop_AutoTextMargin );
3671 xDrawObj->SetDffData( rDffObjData, aObjName, aHyperlink, bVisible, bAutoMargin );
3673 /* Connect textbox data (string, alignment, text orientation) to object.
3674 don't ask for a text-ID, DFF export doesn't set one. */
3675 if( XclImpTextObj* pTextObj = dynamic_cast< XclImpTextObj* >( xDrawObj.get() ) )
3676 if( const XclImpObjTextData* pTextData = rConvData.mrDrawing.FindTextData( rDffObjData.rSpHd ) )
3677 pTextObj->SetTextData( *pTextData );
3679 // copy line and fill formatting of TBX form controls from DFF properties
3680 if( XclImpTbxObjBase* pTbxObj = dynamic_cast< XclImpTbxObjBase* >( xDrawObj.get() ) )
3681 pTbxObj->SetDffProperties( *this );
3683 // try to create a custom SdrObject that overwrites the passed object
3684 rtl::Reference<SdrObject> xNewSdrObj( xDrawObj->CreateSdrObject( *this, rAnchorRect, true ) );
3685 if( xNewSdrObj )
3686 xSdrObj = std::move( xNewSdrObj );
3688 // process the SdrObject
3689 if( xSdrObj )
3691 // filled without color -> set system window color
3692 if( GetPropertyBool( DFF_Prop_fFilled ) && !IsProperty( DFF_Prop_fillColor ) )
3693 xSdrObj->SetMergedItem( XFillColorItem( OUString(), GetPalette().GetColor( EXC_COLOR_WINDOWBACK ) ) );
3695 // additional processing on the SdrObject
3696 xDrawObj->PreProcessSdrObject( *this, *xSdrObj );
3698 /* If the SdrObject will not be inserted into the draw page, delete it
3699 here. Happens e.g. for notes: The PreProcessSdrObject() call above
3700 has inserted the note into the document, and the SdrObject is not
3701 needed anymore. */
3702 if( !xDrawObj->IsInsertSdrObj() )
3703 xSdrObj.clear();
3706 if( xSdrObj )
3708 /* Store the relation between shape ID and SdrObject for connectors.
3709 Must be done here (and not in InsertSdrObject() function),
3710 otherwise all SdrObjects embedded in groups would be lost. */
3711 rConvData.maSolverCont.InsertSdrObjectInfo( *xSdrObj, xDrawObj->GetDffShapeId(), xDrawObj->GetDffFlags() );
3713 /* If the drawing object is embedded in a group object, call
3714 PostProcessSdrObject() here. For top-level objects this will be
3715 done automatically in InsertSdrObject() but grouped shapes are
3716 inserted into their groups somewhere in the SvxMSDffManager base
3717 class without chance of notification. Unfortunately, now this is
3718 called before the object is really inserted into its group object,
3719 but that should not have any effect for grouped objects. */
3720 if( !bIsTopLevel )
3721 xDrawObj->PostProcessSdrObject( *this, *xSdrObj );
3724 return xSdrObj;
3727 SdrObject* XclImpDffConverter::FinalizeObj(DffObjData& rDffObjData, SdrObject* pOldSdrObj )
3729 XclImpDffConvData& rConvData = GetConvData();
3731 /* pOldSdrObj passes a generated SdrObject. This function owns this object
3732 and can modify it. The function has either to return it back to caller
3733 or to delete it by itself. */
3734 rtl::Reference<SdrObject> xSdrObj( pOldSdrObj );
3736 // find the OBJ record data related to the processed shape
3737 XclImpDrawObjRef xDrawObj = rConvData.mrDrawing.FindDrawObj( rDffObjData.rSpHd );
3739 if( xSdrObj && xDrawObj )
3741 // cell anchoring
3742 if ( !rDffObjData.bPageAnchor )
3743 ScDrawLayer::SetCellAnchoredFromPosition( *xSdrObj, GetDoc(), xDrawObj->GetTab(), false );
3746 return xSdrObj.get();
3749 bool XclImpDffConverter::InsertControl( const Reference< XFormComponent >& rxFormComp,
3750 const css::awt::Size& /*rSize*/, Reference< XShape >* pxShape,
3751 bool /*bFloatingCtrl*/ )
3753 if( GetDocShell() ) try
3755 XclImpDffConvData& rConvData = GetConvData();
3756 Reference< XIndexContainer > xFormIC( rConvData.mxCtrlForm, UNO_QUERY_THROW );
3757 Reference< XControlModel > xCtrlModel( rxFormComp, UNO_QUERY_THROW );
3759 // create the control shape
3760 Reference< XShape > xShape( ScfApiHelper::CreateInstance( GetDocShell(), u"com.sun.star.drawing.ControlShape"_ustr ), UNO_QUERY_THROW );
3761 Reference< XControlShape > xCtrlShape( xShape, UNO_QUERY_THROW );
3763 // insert the new control into the form
3764 sal_Int32 nNewIndex = xFormIC->getCount();
3765 xFormIC->insertByIndex( nNewIndex, Any( rxFormComp ) );
3766 // on success: store new index of the control for later use (macro events)
3767 rConvData.mnLastCtrlIndex = nNewIndex;
3769 // set control model at control shape and pass back shape to caller
3770 xCtrlShape->setControl( xCtrlModel );
3771 if( pxShape ) *pxShape = std::move(xShape);
3772 return true;
3774 catch( const Exception& )
3776 OSL_FAIL( "XclImpDffConverter::InsertControl - cannot create form control" );
3779 return false;
3782 // private --------------------------------------------------------------------
3784 XclImpDffConverter::XclImpDffConvData& XclImpDffConverter::GetConvData()
3786 OSL_ENSURE( !maDataStack.empty(), "XclImpDffConverter::GetConvData - no drawing manager on stack" );
3787 return *maDataStack.back();
3790 const XclImpDffConverter::XclImpDffConvData& XclImpDffConverter::GetConvData() const
3792 OSL_ENSURE( !maDataStack.empty(), "XclImpDffConverter::GetConvData - no drawing manager on stack" );
3793 return *maDataStack.back();
3796 OUString XclImpDffConverter::ReadHlinkProperty( SvStream& rDffStrm ) const
3798 /* Reads hyperlink data from a complex DFF property. Contents of this
3799 property are equal to the HLINK record, import of this record is
3800 implemented in class XclImpHyperlink. This function has to create an
3801 instance of the XclImpStream class to be able to reuse the
3802 functionality of XclImpHyperlink. */
3803 OUString aString;
3804 sal_uInt32 nBufferSize = GetPropertyValue( DFF_Prop_pihlShape, 0 );
3805 if( (0 < nBufferSize) && (nBufferSize <= 0xFFFF) && SeekToContent( DFF_Prop_pihlShape, rDffStrm ) )
3807 // create a faked BIFF record that can be read by XclImpStream class
3808 SvMemoryStream aMemStream;
3809 aMemStream.WriteUInt16( 0 ).WriteUInt16( nBufferSize );
3811 // copy from DFF stream to memory stream
3812 ::std::vector< sal_uInt8 > aBuffer( nBufferSize );
3813 sal_uInt8* pnData = aBuffer.data();
3814 if (rDffStrm.ReadBytes(pnData, nBufferSize) == nBufferSize)
3816 aMemStream.WriteBytes(pnData, nBufferSize);
3818 // create BIFF import stream to be able to use XclImpHyperlink class
3819 XclImpStream aXclStrm( aMemStream, GetRoot() );
3820 if( aXclStrm.StartNextRecord() )
3821 aString = XclImpHyperlink::ReadEmbeddedData( aXclStrm );
3824 return aString;
3827 bool XclImpDffConverter::ProcessDgContainer( SvStream& rDffStrm, const DffRecordHeader& rDgHeader )
3829 std::size_t nEndPos = rDgHeader.GetRecEndFilePos();
3830 bool isBreak(false);
3831 while (!isBreak && rDffStrm.good() && rDffStrm.Tell() < nEndPos)
3833 DffRecordHeader aHeader;
3834 ReadDffRecordHeader( rDffStrm, aHeader );
3835 switch( aHeader.nRecType )
3837 case DFF_msofbtSolverContainer:
3838 isBreak = !ProcessSolverContainer( rDffStrm, aHeader );
3839 break;
3840 case DFF_msofbtSpgrContainer:
3841 isBreak = !ProcessShGrContainer( rDffStrm, aHeader );
3842 break;
3843 default:
3844 isBreak = !aHeader.SeekToEndOfRecord( rDffStrm );
3847 // seek to end of drawing page container
3848 isBreak = !rDgHeader.SeekToEndOfRecord( rDffStrm );
3850 // #i12638# #i37900# connector rules
3851 XclImpSolverContainer& rSolverCont = GetConvData().maSolverCont;
3852 rSolverCont.UpdateConnectorRules();
3853 SolveSolver( rSolverCont );
3854 rSolverCont.RemoveConnectorRules();
3855 return !isBreak;
3858 bool XclImpDffConverter::ProcessShGrContainer( SvStream& rDffStrm, const DffRecordHeader& rShGrHeader )
3860 std::size_t nEndPos = rShGrHeader.GetRecEndFilePos();
3861 bool isBreak(false);
3862 while (!isBreak && rDffStrm.good() && rDffStrm.Tell() < nEndPos)
3864 DffRecordHeader aHeader;
3865 ReadDffRecordHeader( rDffStrm, aHeader );
3866 switch( aHeader.nRecType )
3868 case DFF_msofbtSpgrContainer:
3869 case DFF_msofbtSpContainer:
3870 isBreak = !ProcessShContainer( rDffStrm, aHeader );
3871 break;
3872 default:
3873 isBreak = !aHeader.SeekToEndOfRecord( rDffStrm );
3876 // seek to end of shape group container
3877 return rShGrHeader.SeekToEndOfRecord( rDffStrm ) && !isBreak;
3880 bool XclImpDffConverter::ProcessSolverContainer( SvStream& rDffStrm, const DffRecordHeader& rSolverHeader )
3882 // solver container wants to read the solver container header again
3883 rSolverHeader.SeekToBegOfRecord( rDffStrm );
3884 // read the entire solver container
3885 ReadSvxMSDffSolverContainer( rDffStrm, GetConvData().maSolverCont );
3886 // seek to end of solver container
3887 return rSolverHeader.SeekToEndOfRecord( rDffStrm );
3890 bool XclImpDffConverter::ProcessShContainer( SvStream& rDffStrm, const DffRecordHeader& rShHeader )
3892 rShHeader.SeekToBegOfRecord( rDffStrm );
3893 tools::Rectangle aDummy;
3894 XclImpDrawObjClientData aDrawObjClientData;
3895 /* The call to ImportObj() creates and returns a new SdrObject for the
3896 processed shape. We take ownership of the returned object here. If the
3897 shape is a group object, all embedded objects are created recursively,
3898 and the returned group object contains them all. ImportObj() calls the
3899 virtual functions ProcessClientAnchor2() and ProcessObj() and writes
3900 the pointer to the related draw object data (OBJ record) into aDrawObjClientData. */
3901 rtl::Reference<SdrObject> xSdrObj( ImportObj( rDffStrm, aDrawObjClientData, aDummy, aDummy, /*nCalledByGroup*/0, /*pShapeId*/nullptr ) );
3902 if (aDrawObjClientData.m_pTopLevelObj && xSdrObj )
3903 InsertSdrObject( GetConvData().mrSdrPage, *aDrawObjClientData.m_pTopLevelObj, xSdrObj.get() );
3904 return rShHeader.SeekToEndOfRecord( rDffStrm );
3907 void XclImpDffConverter::InsertSdrObject( SdrObjList& rObjList, const XclImpDrawObjBase& rDrawObj, SdrObject* pSdrObj )
3909 XclImpDffConvData& rConvData = GetConvData();
3910 /* Take ownership of the passed object. If insertion fails (e.g. rDrawObj
3911 states to skip insertion), the object is automatically deleted. */
3912 rtl::Reference<SdrObject> xSdrObj( pSdrObj );
3913 if( xSdrObj && rDrawObj.IsInsertSdrObj() )
3915 rObjList.NbcInsertObject( xSdrObj.get() );
3916 // callback to drawing manager for e.g. tracking of used sheet area
3917 rConvData.mrDrawing.OnObjectInserted( rDrawObj );
3918 // callback to drawing object for post processing (use pSdrObj, xSdrObj already released)
3919 rDrawObj.PostProcessSdrObject( *this, *pSdrObj );
3921 /* SdrObject still here? Insertion failed, remove data from shape ID map.
3922 The SdrObject will be destructed then. */
3923 if( xSdrObj )
3924 rConvData.maSolverCont.RemoveSdrObjectInfo( *xSdrObj );
3927 void XclImpDffConverter::InitControlForm()
3929 XclImpDffConvData& rConvData = GetConvData();
3930 if( rConvData.mbHasCtrlForm )
3931 return;
3933 rConvData.mbHasCtrlForm = true;
3934 if( !SupportsOleObjects() )
3935 return;
3939 Reference< XFormsSupplier > xFormsSupplier( rConvData.mrSdrPage.getUnoPage(), UNO_QUERY_THROW );
3940 Reference< XNameContainer > xFormsNC( xFormsSupplier->getForms(), UNO_SET_THROW );
3941 // find or create the Standard form used to insert the imported controls
3942 if( xFormsNC->hasByName( gaStdFormName ) )
3944 xFormsNC->getByName( gaStdFormName ) >>= rConvData.mxCtrlForm;
3946 else if( SfxObjectShell* pDocShell = GetDocShell() )
3948 rConvData.mxCtrlForm.set( ScfApiHelper::CreateInstance( pDocShell, u"com.sun.star.form.component.Form"_ustr ), UNO_QUERY_THROW );
3949 xFormsNC->insertByName( gaStdFormName, Any( rConvData.mxCtrlForm ) );
3952 catch( const Exception& )
3957 // Drawing manager ============================================================
3959 XclImpDrawing::XclImpDrawing( const XclImpRoot& rRoot, bool bOleObjects ) :
3960 XclImpRoot( rRoot ),
3961 mbOleObjs( bOleObjects )
3965 XclImpDrawing::~XclImpDrawing()
3969 Graphic XclImpDrawing::ReadImgData( const XclImpRoot& rRoot, XclImpStream& rStrm )
3971 Graphic aGraphic;
3972 sal_uInt16 nFormat = rStrm.ReaduInt16();
3973 rStrm.Ignore( 2 );//nEnv
3974 sal_uInt32 nDataSize = rStrm.ReaduInt32();
3975 if( nDataSize <= rStrm.GetRecLeft() )
3977 switch( nFormat )
3979 case EXC_IMGDATA_WMF: ReadWmf( aGraphic, rStrm ); break;
3980 case EXC_IMGDATA_BMP: ReadBmp( aGraphic, rRoot, rStrm ); break;
3981 default: OSL_FAIL( "XclImpDrawing::ReadImgData - unknown image format" );
3984 return aGraphic;
3987 void XclImpDrawing::ReadObj( XclImpStream& rStrm )
3989 XclImpDrawObjRef xDrawObj;
3991 /* #i61786# In BIFF8 streams, OBJ records may occur without MSODRAWING
3992 records. In this case, the OBJ records are in BIFF5 format. Do a sanity
3993 check here that there is no DFF data loaded before. */
3994 OSL_ENSURE( maDffStrm.Tell() == 0, "XclImpDrawing::ReadObj - unexpected DFF stream data, OBJ will be ignored" );
3995 if( maDffStrm.Tell() == 0 ) switch( GetBiff() )
3997 case EXC_BIFF3:
3998 xDrawObj = XclImpDrawObjBase::ReadObj3( GetRoot(), rStrm );
3999 break;
4000 case EXC_BIFF4:
4001 xDrawObj = XclImpDrawObjBase::ReadObj4( GetRoot(), rStrm );
4002 break;
4003 case EXC_BIFF5:
4004 case EXC_BIFF8:
4005 xDrawObj = XclImpDrawObjBase::ReadObj5( GetRoot(), rStrm );
4006 break;
4007 default:
4008 DBG_ERROR_BIFF();
4011 if( xDrawObj )
4013 // insert into maRawObjs or into the last open group object
4014 maRawObjs.InsertGrouped( xDrawObj );
4015 // to be able to find objects by ID
4016 maObjMapId[ xDrawObj->GetObjId() ] = xDrawObj;
4020 void XclImpDrawing::ReadMsoDrawing( XclImpStream& rStrm )
4022 OSL_ENSURE_BIFF( GetBiff() == EXC_BIFF8 );
4023 // disable internal CONTINUE handling
4024 rStrm.ResetRecord( false );
4025 // read leading MSODRAWING record
4026 ReadDffRecord( rStrm );
4028 // read following drawing records, but do not start following unrelated record
4029 bool bLoop = true;
4030 while( bLoop ) switch( rStrm.GetNextRecId() )
4032 case EXC_ID_MSODRAWING:
4033 case EXC_ID_MSODRAWINGSEL:
4034 case EXC_ID_CONT:
4035 rStrm.StartNextRecord();
4036 ReadDffRecord( rStrm );
4037 break;
4038 case EXC_ID_OBJ:
4039 rStrm.StartNextRecord();
4040 ReadObj8( rStrm );
4041 break;
4042 case EXC_ID_TXO:
4043 rStrm.StartNextRecord();
4044 ReadTxo( rStrm );
4045 break;
4046 default:
4047 bLoop = false;
4050 // re-enable internal CONTINUE handling
4051 rStrm.ResetRecord( true );
4054 XclImpDrawObjRef XclImpDrawing::FindDrawObj( const DffRecordHeader& rHeader ) const
4056 /* maObjMap stores objects by position of the client data (OBJ record) in
4057 the DFF stream, which is always behind shape start position of the
4058 passed header. The function upper_bound() finds the first element in
4059 the map whose key is greater than the start position of the header. Its
4060 end position is used to test whether the found object is really related
4061 to the shape. */
4062 XclImpDrawObjRef xDrawObj;
4063 XclImpObjMap::const_iterator aIt = maObjMap.upper_bound( rHeader.GetRecBegFilePos() );
4064 if( (aIt != maObjMap.end()) && (aIt->first <= rHeader.GetRecEndFilePos()) )
4065 xDrawObj = aIt->second;
4066 return xDrawObj;
4069 XclImpDrawObjRef XclImpDrawing::FindDrawObj( sal_uInt16 nObjId ) const
4071 XclImpDrawObjRef xDrawObj;
4072 XclImpObjMapById::const_iterator aIt = maObjMapId.find( nObjId );
4073 if( aIt != maObjMapId.end() )
4074 xDrawObj = aIt->second;
4075 return xDrawObj;
4078 const XclImpObjTextData* XclImpDrawing::FindTextData( const DffRecordHeader& rHeader ) const
4080 /* maTextMap stores textbox data by position of the client data (TXO
4081 record) in the DFF stream, which is always behind shape start position
4082 of the passed header. The function upper_bound() finds the first
4083 element in the map whose key is greater than the start position of the
4084 header. Its end position is used to test whether the found object is
4085 really related to the shape. */
4086 XclImpObjTextMap::const_iterator aIt = maTextMap.upper_bound( rHeader.GetRecBegFilePos() );
4087 if( (aIt != maTextMap.end()) && (aIt->first <= rHeader.GetRecEndFilePos()) )
4088 return aIt->second.get();
4089 return nullptr;
4092 void XclImpDrawing::ApplyGroupBoxes()
4094 // sorted: smallest to largest - looking for smallest contained-in GroupBox
4095 // multimap: allows duplicate key values - may have identical areas.
4096 std::multimap<double, XclImpDrawObjRef> aGroupBoxAreaMap;
4097 for (auto& rGroupBox : maObjMapId)
4099 if (rGroupBox.second->GetObjType() != EXC_OBJTYPE_GROUPBOX)
4100 continue;
4101 const tools::Rectangle& rRect = rGroupBox.second->GetDffRect();
4102 const double fArea = double(rRect.GetWidth()) * rRect.GetHeight();
4103 aGroupBoxAreaMap.insert(std::pair<double, XclImpDrawObjRef>(fArea, rGroupBox.second));
4106 for (auto& rGroupedObj : maObjMapId)
4108 auto pRadioButton = dynamic_cast<XclImpOptionButtonObj*>(rGroupedObj.second.get());
4109 if (!pRadioButton || pRadioButton->IsInGroup())
4110 continue;
4112 OUString sGroupName(u"autoGroup_"_ustr);
4113 for (auto& rGroupBox : aGroupBoxAreaMap)
4115 assert(pRadioButton->GetTab() == rGroupBox.second->GetTab() && "impossible right?");
4116 if (!rGroupBox.second->GetDffRect().Contains(pRadioButton->GetDffRect()))
4117 continue;
4119 sGroupName = rGroupBox.second->GetObjName();
4120 if (sGroupName.isEmpty())
4121 sGroupName += "autoGroup_" + OUString::number(rGroupBox.second->GetObjId());
4122 // I ASSUME the smallest box wins in MS Word. (otherwise first? last?)
4123 break;
4125 pRadioButton->SetStringProperty(u"GroupName"_ustr, sGroupName);
4129 void XclImpDrawing::SetSkipObj( sal_uInt16 nObjId )
4131 maSkipObjs.push_back( nObjId );
4134 std::size_t XclImpDrawing::GetProgressSize() const
4136 return std::accumulate(maObjMap.begin(), maObjMap.end(), maRawObjs.GetProgressSize(),
4137 [](const std::size_t& rSum, const XclImpObjMap::value_type& rEntry) { return rSum + rEntry.second->GetProgressSize(); });
4140 void XclImpDrawing::ImplConvertObjects( XclImpDffConverter& rDffConv, SdrModel& rSdrModel, SdrPage& rSdrPage )
4142 //rhbz#636521, disable undo during conversion. faster, smaller and stops
4143 //temp objects being inserted into the undo list
4144 bool bOrigUndoStatus = rSdrModel.IsUndoEnabled();
4145 rSdrModel.EnableUndo(false);
4146 // register this drawing manager at the passed (global) DFF manager
4147 rDffConv.InitializeDrawing( *this, rSdrModel, rSdrPage );
4148 // process list of objects to be skipped
4149 for( const auto& rSkipObj : maSkipObjs )
4150 if( XclImpDrawObjBase* pDrawObj = FindDrawObj( rSkipObj ).get() )
4151 pDrawObj->SetProcessSdrObj( false );
4152 // process drawing objects without DFF data
4153 rDffConv.ProcessDrawing( maRawObjs );
4154 // process all objects in the DFF stream
4155 rDffConv.ProcessDrawing( maDffStrm );
4156 // assign groups based on being contained in the same GroupBox/sheet
4157 ApplyGroupBoxes();
4158 // unregister this drawing manager at the passed (global) DFF manager
4159 rDffConv.FinalizeDrawing();
4160 rSdrModel.EnableUndo(bOrigUndoStatus);
4163 // protected ------------------------------------------------------------------
4165 void XclImpDrawing::AppendRawObject( const XclImpDrawObjRef& rxDrawObj )
4167 OSL_ENSURE( rxDrawObj, "XclImpDrawing::AppendRawObject - unexpected empty reference" );
4168 maRawObjs.push_back( rxDrawObj );
4171 // private --------------------------------------------------------------------
4173 void XclImpDrawing::ReadWmf( Graphic& rGraphic, XclImpStream& rStrm ) // static helper
4175 // extract graphic data from IMGDATA and following CONTINUE records
4176 rStrm.Ignore( 8 );
4177 SvMemoryStream aMemStrm;
4178 rStrm.CopyToStream( aMemStrm, rStrm.GetRecLeft() );
4179 aMemStrm.Seek( STREAM_SEEK_TO_BEGIN );
4180 // import the graphic from memory stream
4181 GDIMetaFile aGDIMetaFile;
4182 if( ::ReadWindowMetafile( aMemStrm, aGDIMetaFile ) )
4183 rGraphic = aGDIMetaFile;
4186 void XclImpDrawing::ReadBmp( Graphic& rGraphic, const XclImpRoot& rRoot, XclImpStream& rStrm ) // static helper
4188 // extract graphic data from IMGDATA and following CONTINUE records
4189 SvMemoryStream aMemStrm;
4191 /* Excel 3 and 4 seem to write broken BMP data. Usually they write a
4192 DIBCOREHEADER (12 bytes) containing width, height, planes = 1, and
4193 pixel depth = 32 bit. After that, 3 unused bytes are added before the
4194 actual pixel data. This does even confuse Excel 5 and later, which
4195 cannot read the image data correctly. */
4196 if( rRoot.GetBiff() <= EXC_BIFF4 )
4198 rStrm.PushPosition();
4199 sal_uInt32 nHdrSize;
4200 sal_uInt16 nWidth, nHeight, nPlanes, nDepth;
4201 nHdrSize = rStrm.ReaduInt32();
4202 nWidth = rStrm.ReaduInt16();
4203 nHeight = rStrm.ReaduInt16();
4204 nPlanes = rStrm.ReaduInt16();
4205 nDepth = rStrm.ReaduInt16();
4206 if( (nHdrSize == 12) && (nPlanes == 1) && (nDepth == 32) )
4208 rStrm.Ignore( 3 );
4209 aMemStrm.SetEndian( SvStreamEndian::LITTLE );
4210 aMemStrm.WriteUInt32( nHdrSize ).WriteUInt16( nWidth ).WriteUInt16( nHeight ).WriteUInt16( nPlanes ).WriteUInt16( nDepth );
4211 rStrm.CopyToStream( aMemStrm, rStrm.GetRecLeft() );
4213 rStrm.PopPosition();
4216 // no special handling above -> just copy the remaining record data
4217 if( aMemStrm.Tell() == 0 )
4218 rStrm.CopyToStream( aMemStrm, rStrm.GetRecLeft() );
4220 // import the graphic from memory stream
4221 aMemStrm.Seek( STREAM_SEEK_TO_BEGIN );
4222 Bitmap aBitmap;
4223 if( ReadDIB(aBitmap, aMemStrm, false) ) // read DIB without file header
4224 rGraphic = BitmapEx(aBitmap);
4227 void XclImpDrawing::ReadDffRecord( XclImpStream& rStrm )
4229 maDffStrm.Seek( STREAM_SEEK_TO_END );
4230 rStrm.CopyRecordToStream( maDffStrm );
4233 void XclImpDrawing::ReadObj8( XclImpStream& rStrm )
4235 XclImpDrawObjRef xDrawObj = XclImpDrawObjBase::ReadObj8( GetRoot(), rStrm );
4236 // store the new object in the internal containers
4237 maObjMap[ maDffStrm.Tell() ] = xDrawObj;
4238 maObjMapId[ xDrawObj->GetObjId() ] = xDrawObj;
4241 void XclImpDrawing::ReadTxo( XclImpStream& rStrm )
4243 XclImpObjTextRef xTextData = std::make_shared<XclImpObjTextData>();
4244 maTextMap[ maDffStrm.Tell() ] = xTextData;
4246 // 1) read the TXO record
4247 xTextData->maData.ReadTxo8( rStrm );
4249 // 2) first CONTINUE with string
4250 xTextData->mxString.reset();
4251 bool bValid = true;
4252 if( xTextData->maData.mnTextLen > 0 )
4254 bValid = (rStrm.GetNextRecId() == EXC_ID_CONT) && rStrm.StartNextRecord();
4255 OSL_ENSURE( bValid, "XclImpDrawing::ReadTxo - missing CONTINUE record" );
4256 if( bValid )
4257 xTextData->mxString = std::make_shared<XclImpString>( rStrm.ReadUniString( xTextData->maData.mnTextLen ) );
4260 // 3) second CONTINUE with formatting runs
4261 if( xTextData->maData.mnFormatSize > 0 )
4263 bValid = (rStrm.GetNextRecId() == EXC_ID_CONT) && rStrm.StartNextRecord();
4264 OSL_ENSURE( bValid, "XclImpDrawing::ReadTxo - missing CONTINUE record" );
4265 if( bValid )
4266 xTextData->ReadFormats( rStrm );
4270 XclImpSheetDrawing::XclImpSheetDrawing( const XclImpRoot& rRoot, SCTAB nScTab ) :
4271 XclImpDrawing( rRoot, true ),
4272 maScUsedArea( ScAddress::INITIALIZE_INVALID )
4274 maScUsedArea.aStart.SetTab( nScTab );
4275 maScUsedArea.aEnd.SetTab( nScTab );
4278 void XclImpSheetDrawing::ReadNote( XclImpStream& rStrm )
4280 switch( GetBiff() )
4282 case EXC_BIFF2:
4283 case EXC_BIFF3:
4284 case EXC_BIFF4:
4285 case EXC_BIFF5:
4286 ReadNote3( rStrm );
4287 break;
4288 case EXC_BIFF8:
4289 ReadNote8( rStrm );
4290 break;
4291 default:
4292 DBG_ERROR_BIFF();
4296 void XclImpSheetDrawing::ReadTabChart( XclImpStream& rStrm )
4298 OSL_ENSURE_BIFF( GetBiff() >= EXC_BIFF5 );
4299 auto xChartObj = std::make_shared<XclImpChartObj>( GetRoot(), true );
4300 xChartObj->ReadChartSubStream( rStrm );
4301 // insert the chart as raw object without connected DFF data
4302 AppendRawObject( xChartObj );
4305 void XclImpSheetDrawing::ConvertObjects( XclImpDffConverter& rDffConv )
4307 if( SdrModel* pSdrModel = GetDoc().GetDrawLayer() )
4308 if( SdrPage* pSdrPage = GetSdrPage( maScUsedArea.aStart.Tab() ) )
4309 ImplConvertObjects( rDffConv, *pSdrModel, *pSdrPage );
4312 tools::Rectangle XclImpSheetDrawing::CalcAnchorRect( const XclObjAnchor& rAnchor, bool /*bDffAnchor*/ ) const
4314 return rAnchor.GetRect( GetRoot(), maScUsedArea.aStart.Tab(), MapUnit::Map100thMM );
4317 void XclImpSheetDrawing::OnObjectInserted( const XclImpDrawObjBase& rDrawObj )
4319 ScRange aScObjArea = rDrawObj.GetUsedArea( maScUsedArea.aStart.Tab() );
4320 if( aScObjArea.IsValid() )
4321 maScUsedArea.ExtendTo( aScObjArea );
4324 // private --------------------------------------------------------------------
4326 void XclImpSheetDrawing::ReadNote3( XclImpStream& rStrm )
4328 XclAddress aXclPos;
4329 rStrm >> aXclPos;
4330 sal_uInt16 nTotalLen = rStrm.ReaduInt16();
4332 ScAddress aScNotePos( ScAddress::UNINITIALIZED );
4333 if( !GetAddressConverter().ConvertAddress( aScNotePos, aXclPos, maScUsedArea.aStart.Tab(), true ) )
4334 return;
4336 sal_uInt16 nPartLen = ::std::min( nTotalLen, static_cast< sal_uInt16 >( rStrm.GetRecLeft() ) );
4337 OUStringBuffer aNoteText(rStrm.ReadRawByteString( nPartLen ));
4338 nTotalLen = nTotalLen - nPartLen;
4339 while (true)
4341 if (!nTotalLen)
4342 break;
4343 if (rStrm.GetNextRecId() != EXC_ID_NOTE)
4344 break;
4345 if (!rStrm.StartNextRecord())
4346 break;
4347 rStrm >> aXclPos;
4348 nPartLen = rStrm.ReaduInt16();
4349 OSL_ENSURE( aXclPos.mnRow == 0xFFFF, "XclImpObjectManager::ReadNote3 - missing continuation NOTE record" );
4350 if( aXclPos.mnRow == 0xFFFF )
4352 OSL_ENSURE( nPartLen <= nTotalLen, "XclImpObjectManager::ReadNote3 - string too long" );
4353 aNoteText.append(rStrm.ReadRawByteString( nPartLen ));
4354 nTotalLen = nTotalLen - ::std::min( nTotalLen, nPartLen );
4356 else
4358 // seems to be a new note, record already started -> load the note
4359 rStrm.Seek( EXC_REC_SEEK_TO_BEGIN );
4360 ReadNote( rStrm );
4361 nTotalLen = 0;
4364 ScNoteUtil::CreateNoteFromString( GetDoc(), aScNotePos, aNoteText.makeStringAndClear(), false, false );
4367 void XclImpSheetDrawing::ReadNote8( XclImpStream& rStrm )
4369 XclAddress aXclPos;
4370 sal_uInt16 nFlags, nObjId;
4371 rStrm >> aXclPos;
4372 nFlags = rStrm.ReaduInt16();
4373 nObjId = rStrm.ReaduInt16();
4375 ScAddress aScNotePos( ScAddress::UNINITIALIZED );
4376 if( GetAddressConverter().ConvertAddress( aScNotePos, aXclPos, maScUsedArea.aStart.Tab(), true ) )
4377 if( nObjId != EXC_OBJ_INVALID_ID )
4378 if( XclImpNoteObj* pNoteObj = dynamic_cast< XclImpNoteObj* >( FindDrawObj( nObjId ).get() ) )
4379 pNoteObj->SetNoteData( aScNotePos, nFlags );
4382 // The object manager =========================================================
4384 XclImpObjectManager::XclImpObjectManager( const XclImpRoot& rRoot ) :
4385 XclImpRoot( rRoot )
4387 maDefObjNames[ EXC_OBJTYPE_GROUP ] = "Group";
4388 maDefObjNames[ EXC_OBJTYPE_LINE ] = ScResId( STR_SHAPE_LINE );
4389 maDefObjNames[ EXC_OBJTYPE_RECTANGLE ] = ScResId( STR_SHAPE_RECTANGLE );
4390 maDefObjNames[ EXC_OBJTYPE_OVAL ] = ScResId( STR_SHAPE_OVAL );
4391 maDefObjNames[ EXC_OBJTYPE_ARC ] = "Arc";
4392 maDefObjNames[ EXC_OBJTYPE_CHART ] = "Chart";
4393 maDefObjNames[ EXC_OBJTYPE_TEXT ] = "Text";
4394 maDefObjNames[ EXC_OBJTYPE_BUTTON ] = ScResId( STR_FORM_BUTTON );
4395 maDefObjNames[ EXC_OBJTYPE_PICTURE ] = "Picture";
4396 maDefObjNames[ EXC_OBJTYPE_POLYGON ] = "Freeform";
4397 maDefObjNames[ EXC_OBJTYPE_CHECKBOX ] = ScResId( STR_FORM_CHECKBOX );
4398 maDefObjNames[ EXC_OBJTYPE_OPTIONBUTTON ] = ScResId( STR_FORM_OPTIONBUTTON );
4399 maDefObjNames[ EXC_OBJTYPE_EDIT ] = "Edit Box";
4400 maDefObjNames[ EXC_OBJTYPE_LABEL ] = ScResId( STR_FORM_LABEL );
4401 maDefObjNames[ EXC_OBJTYPE_DIALOG ] = "Dialog Frame";
4402 maDefObjNames[ EXC_OBJTYPE_SPIN ] = ScResId( STR_FORM_SPINNER );
4403 maDefObjNames[ EXC_OBJTYPE_SCROLLBAR ] = ScResId( STR_FORM_SCROLLBAR );
4404 maDefObjNames[ EXC_OBJTYPE_LISTBOX ] = ScResId( STR_FORM_LISTBOX );
4405 maDefObjNames[ EXC_OBJTYPE_GROUPBOX ] = ScResId( STR_FORM_GROUPBOX );
4406 maDefObjNames[ EXC_OBJTYPE_DROPDOWN ] = ScResId( STR_FORM_DROPDOWN );
4407 maDefObjNames[ EXC_OBJTYPE_NOTE ] = "Comment";
4408 maDefObjNames[ EXC_OBJTYPE_DRAWING ] = ScResId( STR_SHAPE_AUTOSHAPE );
4411 XclImpObjectManager::~XclImpObjectManager()
4415 void XclImpObjectManager::ReadMsoDrawingGroup( XclImpStream& rStrm )
4417 OSL_ENSURE_BIFF( GetBiff() == EXC_BIFF8 );
4418 // Excel continues this record with MSODRAWINGGROUP and CONTINUE records, hmm.
4419 rStrm.ResetRecord( true, EXC_ID_MSODRAWINGGROUP );
4420 maDggStrm.Seek( STREAM_SEEK_TO_END );
4421 rStrm.CopyRecordToStream( maDggStrm );
4424 XclImpSheetDrawing& XclImpObjectManager::GetSheetDrawing( SCTAB nScTab )
4426 XclImpSheetDrawingRef& rxDrawing = maSheetDrawings[ nScTab ];
4427 if( !rxDrawing )
4428 rxDrawing = std::make_shared<XclImpSheetDrawing>( GetRoot(), nScTab );
4429 return *rxDrawing;
4432 void XclImpObjectManager::ConvertObjects()
4434 // do nothing if the document does not contain a drawing layer
4435 if( !GetDoc().GetDrawLayer() )
4436 return;
4438 // get total progress bar size for all sheet drawing managers
4439 std::size_t nProgressSize = std::accumulate(maSheetDrawings.begin(), maSheetDrawings.end(), std::size_t(0),
4440 [](const std::size_t& rSum, const XclImpSheetDrawingMap::value_type& rEntry) { return rSum + rEntry.second->GetProgressSize(); });
4441 // nothing to do if progress bar is zero (no objects present)
4442 if( nProgressSize == 0 )
4443 return;
4445 XclImpDffConverter aDffConv( GetRoot(), maDggStrm );
4446 aDffConv.StartProgressBar( nProgressSize );
4447 for( auto& rEntry : maSheetDrawings )
4448 rEntry.second->ConvertObjects( aDffConv );
4450 // #i112436# don't call ScChartListenerCollection::SetDirty here,
4451 // instead use InterpretDirtyCells in ScDocument::CalcAfterLoad.
4454 OUString XclImpObjectManager::GetDefaultObjName( const XclImpDrawObjBase& rDrawObj ) const
4456 OUString aDefName;
4457 DefObjNameMap::const_iterator aIt = maDefObjNames.find( rDrawObj.GetObjType() );
4458 if( aIt != maDefObjNames.end() )
4459 aDefName = aIt->second;
4460 return aDefName + " " + OUString::number(static_cast<sal_Int32>(rDrawObj.GetObjId()));
4463 ScRange XclImpObjectManager::GetUsedArea( SCTAB nScTab ) const
4465 XclImpSheetDrawingMap::const_iterator aIt = maSheetDrawings.find( nScTab );
4466 if( aIt != maSheetDrawings.end() )
4467 return aIt->second->GetUsedArea();
4468 return ScRange( ScAddress::INITIALIZE_INVALID );
4471 // DFF property set helper ====================================================
4473 XclImpDffPropSet::XclImpDffPropSet( const XclImpRoot& rRoot ) :
4474 XclImpRoot( rRoot ),
4475 maDffConv( rRoot, maDummyStrm )
4479 void XclImpDffPropSet::Read( XclImpStream& rStrm )
4481 sal_uInt32 nPropSetSize;
4483 rStrm.PushPosition();
4484 rStrm.Ignore( 4 );
4485 nPropSetSize = rStrm.ReaduInt32();
4486 rStrm.PopPosition();
4488 mxMemStrm.reset( new SvMemoryStream );
4489 rStrm.CopyToStream( *mxMemStrm, 8 + nPropSetSize );
4490 mxMemStrm->Seek( STREAM_SEEK_TO_BEGIN );
4491 maDffConv.ReadPropSet( *mxMemStrm, nullptr );
4494 sal_uInt32 XclImpDffPropSet::GetPropertyValue( sal_uInt16 nPropId ) const
4496 return maDffConv.GetPropertyValue( nPropId, 0 );
4499 void XclImpDffPropSet::FillToItemSet( SfxItemSet& rItemSet ) const
4501 if( mxMemStrm )
4502 maDffConv.ApplyAttributes( *mxMemStrm, rItemSet );
4505 XclImpStream& operator>>( XclImpStream& rStrm, XclImpDffPropSet& rPropSet )
4507 rPropSet.Read( rStrm );
4508 return rStrm;
4511 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */