LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / sc / source / filter / excel / xiescher.cxx
blob298517b0f5b0e2415bd6e4e7de114a0651d2a56a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <xiescher.hxx>
22 #include <com/sun/star/beans/NamedValue.hpp>
23 #include <com/sun/star/container/XIndexContainer.hpp>
24 #include <com/sun/star/container/XNameContainer.hpp>
25 #include <com/sun/star/embed/Aspects.hpp>
26 #include <com/sun/star/embed/XEmbeddedObject.hpp>
27 #include <com/sun/star/embed/XEmbedPersist.hpp>
28 #include <com/sun/star/awt/PushButtonType.hpp>
29 #include <com/sun/star/awt/ScrollBarOrientation.hpp>
30 #include <com/sun/star/awt/VisualEffect.hpp>
31 #include <com/sun/star/style/VerticalAlignment.hpp>
32 #include <com/sun/star/drawing/XControlShape.hpp>
33 #include <com/sun/star/form/XForm.hpp>
34 #include <com/sun/star/form/XFormsSupplier.hpp>
35 #include <com/sun/star/form/binding/XBindableValue.hpp>
36 #include <com/sun/star/form/binding/XValueBinding.hpp>
37 #include <com/sun/star/form/binding/XListEntrySink.hpp>
38 #include <com/sun/star/form/binding/XListEntrySource.hpp>
39 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
40 #include <com/sun/star/script/XEventAttacherManager.hpp>
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include <com/sun/star/frame/XModel.hpp>
44 #include <sfx2/objsh.hxx>
45 #include <unotools/moduleoptions.hxx>
46 #include <unotools/configmgr.hxx>
47 #include <unotools/fltrcfg.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 <userdat.hxx>
106 #include <unonames.hxx>
107 #include <convuno.hxx>
108 #include <postit.hxx>
109 #include <globstr.hrc>
110 #include <scresid.hxx>
112 #include <fprogressbar.hxx>
113 #include <xltracer.hxx>
114 #include <xistream.hxx>
115 #include <xihelper.hxx>
116 #include <xiformula.hxx>
117 #include <xilink.hxx>
118 #include <xistyle.hxx>
119 #include <xipage.hxx>
120 #include <xichart.hxx>
121 #include <xicontent.hxx>
122 #include <scextopt.hxx>
124 #include <namebuff.hxx>
125 #include <sfx2/docfile.hxx>
126 #include <memory>
127 #include <numeric>
128 #include <string_view>
129 #include <utility>
131 using namespace com::sun::star;
132 using ::com::sun::star::uno::makeAny;
133 using ::com::sun::star::uno::Any;
134 using ::com::sun::star::beans::XPropertySet;
135 using ::com::sun::star::uno::makeAny;
136 using ::com::sun::star::uno::Exception;
137 using ::com::sun::star::uno::Reference;
138 using ::com::sun::star::uno::Sequence;
139 using ::com::sun::star::uno::UNO_QUERY;
140 using ::com::sun::star::uno::UNO_QUERY_THROW;
141 using ::com::sun::star::uno::UNO_SET_THROW;
142 using ::com::sun::star::beans::NamedValue;
143 using ::com::sun::star::lang::XMultiServiceFactory;
144 using ::com::sun::star::container::XIndexContainer;
145 using ::com::sun::star::container::XNameContainer;
146 using ::com::sun::star::frame::XModel;
147 using ::com::sun::star::awt::XControlModel;
148 using ::com::sun::star::embed::XEmbeddedObject;
149 using ::com::sun::star::embed::XEmbedPersist;
150 using ::com::sun::star::drawing::XControlShape;
151 using ::com::sun::star::drawing::XShape;
152 using ::com::sun::star::form::XFormComponent;
153 using ::com::sun::star::form::XFormsSupplier;
154 using ::com::sun::star::form::binding::XBindableValue;
155 using ::com::sun::star::form::binding::XValueBinding;
156 using ::com::sun::star::form::binding::XListEntrySink;
157 using ::com::sun::star::form::binding::XListEntrySource;
158 using ::com::sun::star::script::ScriptEventDescriptor;
159 using ::com::sun::star::script::XEventAttacherManager;
160 using ::com::sun::star::table::CellAddress;
161 using ::com::sun::star::table::CellRangeAddress;
163 // Drawing objects ============================================================
165 XclImpDrawObjBase::XclImpDrawObjBase( const XclImpRoot& rRoot ) :
166 XclImpRoot( rRoot ),
167 mnObjId( EXC_OBJ_INVALID_ID ),
168 mnTab( 0 ),
169 mnObjType( EXC_OBJTYPE_UNKNOWN ),
170 mnDffShapeId( 0 ),
171 mnDffFlags( ShapeFlag::NONE ),
172 mbHasAnchor( false ),
173 mbHidden( false ),
174 mbVisible( true ),
175 mbPrintable( true ),
176 mbAreaObj( false ),
177 mbAutoMargin( true ),
178 mbSimpleMacro( true ),
179 mbProcessSdr( true ),
180 mbInsertSdr( true ),
181 mbCustomDff( false ),
182 mbNotifyMacroEventRead( false )
186 XclImpDrawObjBase::~XclImpDrawObjBase()
190 XclImpDrawObjRef XclImpDrawObjBase::ReadObj3( const XclImpRoot& rRoot, XclImpStream& rStrm )
192 XclImpDrawObjRef xDrawObj;
194 if( rStrm.GetRecLeft() >= 30 )
196 sal_uInt16 nObjType;
197 rStrm.Ignore( 4 );
198 nObjType = rStrm.ReaduInt16();
199 switch( nObjType )
201 case EXC_OBJTYPE_GROUP: xDrawObj= std::make_shared<XclImpGroupObj>( rRoot ); break;
202 case EXC_OBJTYPE_LINE: xDrawObj= std::make_shared<XclImpLineObj>( rRoot ); break;
203 case EXC_OBJTYPE_RECTANGLE: xDrawObj= std::make_shared<XclImpRectObj>( rRoot ); break;
204 case EXC_OBJTYPE_OVAL: xDrawObj= std::make_shared<XclImpOvalObj>( rRoot ); break;
205 case EXC_OBJTYPE_ARC: xDrawObj= std::make_shared<XclImpArcObj>( rRoot ); break;
206 case EXC_OBJTYPE_CHART: xDrawObj= std::make_shared<XclImpChartObj>( rRoot ); break;
207 case EXC_OBJTYPE_TEXT: xDrawObj= std::make_shared<XclImpTextObj>( rRoot ); break;
208 case EXC_OBJTYPE_BUTTON: xDrawObj= std::make_shared<XclImpButtonObj>( rRoot ); break;
209 case EXC_OBJTYPE_PICTURE: xDrawObj= std::make_shared<XclImpPictureObj>( rRoot ); break;
210 default:
211 SAL_WARN("sc.filter", "XclImpDrawObjBase::ReadObj3 - unknown object type 0x" << std::hex << nObjType );
212 rRoot.GetTracer().TraceUnsupportedObjects();
216 if (!xDrawObj)
218 xDrawObj = std::make_shared<XclImpPhObj>(rRoot);
221 xDrawObj->mnTab = rRoot.GetCurrScTab();
222 xDrawObj->ImplReadObj3( rStrm );
223 return xDrawObj;
226 XclImpDrawObjRef XclImpDrawObjBase::ReadObj4( const XclImpRoot& rRoot, XclImpStream& rStrm )
228 XclImpDrawObjRef xDrawObj;
230 if( rStrm.GetRecLeft() >= 30 )
232 sal_uInt16 nObjType;
233 rStrm.Ignore( 4 );
234 nObjType = rStrm.ReaduInt16();
235 switch( nObjType )
237 case EXC_OBJTYPE_GROUP: xDrawObj = std::make_shared<XclImpGroupObj>( rRoot ); break;
238 case EXC_OBJTYPE_LINE: xDrawObj = std::make_shared<XclImpLineObj>( rRoot ); break;
239 case EXC_OBJTYPE_RECTANGLE: xDrawObj = std::make_shared<XclImpRectObj>( rRoot ); break;
240 case EXC_OBJTYPE_OVAL: xDrawObj = std::make_shared<XclImpOvalObj>( rRoot ); break;
241 case EXC_OBJTYPE_ARC: xDrawObj = std::make_shared<XclImpArcObj>( rRoot ); break;
242 case EXC_OBJTYPE_CHART: xDrawObj = std::make_shared<XclImpChartObj>( rRoot ); break;
243 case EXC_OBJTYPE_TEXT: xDrawObj = std::make_shared<XclImpTextObj>( rRoot ); break;
244 case EXC_OBJTYPE_BUTTON: xDrawObj = std::make_shared<XclImpButtonObj>( rRoot ); break;
245 case EXC_OBJTYPE_PICTURE: xDrawObj = std::make_shared<XclImpPictureObj>( rRoot ); break;
246 case EXC_OBJTYPE_POLYGON: xDrawObj = std::make_shared<XclImpPolygonObj>( rRoot ); break;
247 default:
248 SAL_WARN("sc.filter", "XclImpDrawObjBase::ReadObj4 - unknown object type 0x" << std::hex << nObjType );
249 rRoot.GetTracer().TraceUnsupportedObjects();
253 if (!xDrawObj)
255 xDrawObj = std::make_shared<XclImpPhObj>(rRoot);
258 xDrawObj->mnTab = rRoot.GetCurrScTab();
259 xDrawObj->ImplReadObj4( rStrm );
260 return xDrawObj;
263 XclImpDrawObjRef XclImpDrawObjBase::ReadObj5( const XclImpRoot& rRoot, XclImpStream& rStrm )
265 XclImpDrawObjRef xDrawObj;
267 if( rStrm.GetRecLeft() >= 34 )
269 sal_uInt16 nObjType(EXC_OBJTYPE_UNKNOWN);
270 rStrm.Ignore( 4 );
271 nObjType = rStrm.ReaduInt16();
272 switch( nObjType )
274 case EXC_OBJTYPE_GROUP: xDrawObj = std::make_shared<XclImpGroupObj>( rRoot ); break;
275 case EXC_OBJTYPE_LINE: xDrawObj = std::make_shared<XclImpLineObj>( rRoot ); break;
276 case EXC_OBJTYPE_RECTANGLE: xDrawObj = std::make_shared<XclImpRectObj>( rRoot ); break;
277 case EXC_OBJTYPE_OVAL: xDrawObj = std::make_shared<XclImpOvalObj>( rRoot ); break;
278 case EXC_OBJTYPE_ARC: xDrawObj = std::make_shared<XclImpArcObj>( rRoot ); break;
279 case EXC_OBJTYPE_CHART: xDrawObj = std::make_shared<XclImpChartObj>( rRoot ); break;
280 case EXC_OBJTYPE_TEXT: xDrawObj = std::make_shared<XclImpTextObj>( rRoot ); break;
281 case EXC_OBJTYPE_BUTTON: xDrawObj = std::make_shared<XclImpButtonObj>( rRoot ); break;
282 case EXC_OBJTYPE_PICTURE: xDrawObj = std::make_shared<XclImpPictureObj>( rRoot ); break;
283 case EXC_OBJTYPE_POLYGON: xDrawObj = std::make_shared<XclImpPolygonObj>( rRoot ); break;
284 case EXC_OBJTYPE_CHECKBOX: xDrawObj = std::make_shared<XclImpCheckBoxObj>( rRoot ); break;
285 case EXC_OBJTYPE_OPTIONBUTTON: xDrawObj = std::make_shared<XclImpOptionButtonObj>( rRoot ); break;
286 case EXC_OBJTYPE_EDIT: xDrawObj = std::make_shared<XclImpEditObj>( rRoot ); break;
287 case EXC_OBJTYPE_LABEL: xDrawObj = std::make_shared<XclImpLabelObj>( rRoot ); break;
288 case EXC_OBJTYPE_DIALOG: xDrawObj = std::make_shared<XclImpDialogObj>( rRoot ); break;
289 case EXC_OBJTYPE_SPIN: xDrawObj = std::make_shared<XclImpSpinButtonObj>( rRoot ); break;
290 case EXC_OBJTYPE_SCROLLBAR: xDrawObj = std::make_shared<XclImpScrollBarObj>( rRoot ); break;
291 case EXC_OBJTYPE_LISTBOX: xDrawObj = std::make_shared<XclImpListBoxObj>( rRoot ); break;
292 case EXC_OBJTYPE_GROUPBOX: xDrawObj = std::make_shared<XclImpGroupBoxObj>( rRoot ); break;
293 case EXC_OBJTYPE_DROPDOWN: xDrawObj = std::make_shared<XclImpDropDownObj>( rRoot ); break;
294 default:
295 SAL_WARN("sc.filter", "XclImpDrawObjBase::ReadObj5 - unknown object type 0x" << std::hex << nObjType );
296 rRoot.GetTracer().TraceUnsupportedObjects();
297 xDrawObj = std::make_shared<XclImpPhObj>( rRoot );
301 OSL_ENSURE(xDrawObj, "object import failed");
303 if (xDrawObj)
305 xDrawObj->mnTab = rRoot.GetCurrScTab();
306 xDrawObj->ImplReadObj5( rStrm );
308 return xDrawObj;
311 XclImpDrawObjRef XclImpDrawObjBase::ReadObj8( const XclImpRoot& rRoot, XclImpStream& rStrm )
313 XclImpDrawObjRef xDrawObj;
315 if( rStrm.GetRecLeft() >= 10 )
317 sal_uInt16 nSubRecId(0), nSubRecSize(0), nObjType(0);
318 nSubRecId = rStrm.ReaduInt16();
319 nSubRecSize = rStrm.ReaduInt16();
320 nObjType = rStrm.ReaduInt16();
321 OSL_ENSURE( nSubRecId == EXC_ID_OBJCMO, "XclImpDrawObjBase::ReadObj8 - OBJCMO subrecord expected" );
322 if( (nSubRecId == EXC_ID_OBJCMO) && (nSubRecSize >= 6) )
324 switch( nObjType )
326 // in BIFF8, all simple objects support text
327 case EXC_OBJTYPE_LINE:
328 case EXC_OBJTYPE_ARC:
329 xDrawObj = std::make_shared<XclImpTextObj>( rRoot );
330 // lines and arcs may be 2-dimensional
331 xDrawObj->SetAreaObj( false );
332 break;
334 // in BIFF8, all simple objects support text
335 case EXC_OBJTYPE_RECTANGLE:
336 case EXC_OBJTYPE_OVAL:
337 case EXC_OBJTYPE_POLYGON:
338 case EXC_OBJTYPE_DRAWING:
339 case EXC_OBJTYPE_TEXT:
340 xDrawObj = std::make_shared<XclImpTextObj>( rRoot );
341 break;
343 case EXC_OBJTYPE_GROUP: xDrawObj = std::make_shared<XclImpGroupObj>( rRoot ); break;
344 case EXC_OBJTYPE_CHART: xDrawObj = std::make_shared<XclImpChartObj>( rRoot ); break;
345 case EXC_OBJTYPE_BUTTON: xDrawObj = std::make_shared<XclImpButtonObj>( rRoot ); break;
346 case EXC_OBJTYPE_PICTURE: xDrawObj = std::make_shared<XclImpPictureObj>( rRoot ); break;
347 case EXC_OBJTYPE_CHECKBOX: xDrawObj = std::make_shared<XclImpCheckBoxObj>( rRoot ); break;
348 case EXC_OBJTYPE_OPTIONBUTTON: xDrawObj = std::make_shared<XclImpOptionButtonObj>( rRoot ); break;
349 case EXC_OBJTYPE_EDIT: xDrawObj = std::make_shared<XclImpEditObj>( rRoot ); break;
350 case EXC_OBJTYPE_LABEL: xDrawObj = std::make_shared<XclImpLabelObj>( rRoot ); break;
351 case EXC_OBJTYPE_DIALOG: xDrawObj = std::make_shared<XclImpDialogObj>( rRoot ); break;
352 case EXC_OBJTYPE_SPIN: xDrawObj = std::make_shared<XclImpSpinButtonObj>( rRoot ); break;
353 case EXC_OBJTYPE_SCROLLBAR: xDrawObj = std::make_shared<XclImpScrollBarObj>( rRoot ); break;
354 case EXC_OBJTYPE_LISTBOX: xDrawObj = std::make_shared<XclImpListBoxObj>( rRoot ); break;
355 case EXC_OBJTYPE_GROUPBOX: xDrawObj = std::make_shared<XclImpGroupBoxObj>( rRoot ); break;
356 case EXC_OBJTYPE_DROPDOWN: xDrawObj = std::make_shared<XclImpDropDownObj>( rRoot ); break;
357 case EXC_OBJTYPE_NOTE: xDrawObj = std::make_shared<XclImpNoteObj>( rRoot ); break;
359 default:
360 SAL_WARN("sc.filter", "XclImpDrawObjBase::ReadObj8 - unknown object type 0x" << std::hex << nObjType );
361 rRoot.GetTracer().TraceUnsupportedObjects();
366 if (!xDrawObj) //ensure placeholder for unknown or broken records
368 SAL_WARN( "sc.filter", "XclImpDrawObjBase::ReadObj8 import failed, substituting placeholder");
369 xDrawObj = std::make_shared<XclImpPhObj>( rRoot );
372 xDrawObj->mnTab = rRoot.GetCurrScTab();
373 xDrawObj->ImplReadObj8( rStrm );
374 return xDrawObj;
377 void XclImpDrawObjBase::SetAnchor( const XclObjAnchor& rAnchor )
379 maAnchor = rAnchor;
380 mbHasAnchor = true;
383 void XclImpDrawObjBase::SetDffData(
384 const DffObjData& rDffObjData, const OUString& rObjName, const OUString& rHyperlink,
385 bool bVisible, bool bAutoMargin )
387 mnDffShapeId = rDffObjData.nShapeId;
388 mnDffFlags = rDffObjData.nSpFlags;
389 maObjName = rObjName;
390 maHyperlink = rHyperlink;
391 mbVisible = bVisible;
392 mbAutoMargin = bAutoMargin;
395 OUString XclImpDrawObjBase::GetObjName() const
397 /* #i51348# Always return a non-empty name. Create English
398 default names depending on the object type. This is not implemented as
399 virtual functions in derived classes, as class type and object type may
400 not match. */
401 return maObjName.isEmpty() ? GetObjectManager().GetDefaultObjName(*this) : maObjName;
404 const XclObjAnchor* XclImpDrawObjBase::GetAnchor() const
406 return mbHasAnchor ? &maAnchor : nullptr;
409 bool XclImpDrawObjBase::IsValidSize( const tools::Rectangle& rAnchorRect ) const
411 // XclObjAnchor rounds up the width, width of 3 is the result of an Excel width of 0
412 return mbAreaObj ?
413 ((rAnchorRect.GetWidth() > 3) && (rAnchorRect.GetHeight() > 1)) :
414 ((rAnchorRect.GetWidth() > 3) || (rAnchorRect.GetHeight() > 1));
417 ScRange XclImpDrawObjBase::GetUsedArea( SCTAB nScTab ) const
419 ScRange aScUsedArea( ScAddress::INITIALIZE_INVALID );
420 // #i44077# object inserted -> update used area for OLE object import
421 if( mbHasAnchor && GetAddressConverter().ConvertRange( aScUsedArea, maAnchor, nScTab, nScTab, false ) )
423 // reduce range, if object ends directly on borders between two columns or rows
424 if( (maAnchor.mnRX == 0) && (aScUsedArea.aStart.Col() < aScUsedArea.aEnd.Col()) )
425 aScUsedArea.aEnd.IncCol( -1 );
426 if( (maAnchor.mnBY == 0) && (aScUsedArea.aStart.Row() < aScUsedArea.aEnd.Row()) )
427 aScUsedArea.aEnd.IncRow( -1 );
429 return aScUsedArea;
432 std::size_t XclImpDrawObjBase::GetProgressSize() const
434 return DoGetProgressSize();
437 SdrObjectUniquePtr XclImpDrawObjBase::CreateSdrObject( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect, bool bIsDff ) const
439 SdrObjectUniquePtr xSdrObj;
440 if( bIsDff && !mbCustomDff )
442 rDffConv.Progress( GetProgressSize() );
444 else
446 xSdrObj = DoCreateSdrObj( rDffConv, rAnchorRect );
448 //added for exporting OCX control
449 /* mnObjType value set should be as below table:
450 0x0000 Group 0x0001 Line
451 0x0002 Rectangle 0x0003 Oval
452 0x0004 Arc 0x0005 Chart
453 0x0006 Text 0x0009 Polygon
454 +-----------------------------------------------------+
455 OCX ==>| 0x0008 Picture |
456 +-----------------------------------------------------+
457 | 0x0007 Button |
458 | 0x000B Checkbox 0x000C Radio button |
459 | 0x000D Edit box 0x000E Label |
460 TBX ==> | 0x000F Dialog box 0x0010 Spin control |
461 | 0x0011 Scrollbar 0x0012 List |
462 | 0x0013 Group box 0x0014 Dropdown list |
463 +-----------------------------------------------------+
464 0x0019 Note 0x001E OfficeArt object
466 if( xSdrObj && xSdrObj->IsUnoObj() &&
467 ( (mnObjType < 25 && mnObjType > 10) || mnObjType == 7 || mnObjType == 8 ) )
469 SdrUnoObj* pSdrUnoObj = dynamic_cast< SdrUnoObj* >( xSdrObj.get() );
470 if( pSdrUnoObj != nullptr )
472 const Reference< XControlModel >& xCtrlModel = pSdrUnoObj->GetUnoControlModel();
473 Reference< XPropertySet > xPropSet(xCtrlModel,UNO_QUERY);
474 static constexpr OUStringLiteral sPropertyName(u"ControlTypeinMSO");
476 enum { eCreateFromOffice = 0, eCreateFromMSTBXControl, eCreateFromMSOCXControl };
478 if( mnObjType == 7 || (mnObjType < 25 && mnObjType > 10) )//TBX
482 //Need summary type for export. Detail type(checkbox, button ...) has been contained by mnObjType
483 const sal_Int16 nTBXControlType = eCreateFromMSTBXControl ;
484 xPropSet->setPropertyValue(sPropertyName, Any(nTBXControlType));
486 catch(const Exception&)
488 SAL_WARN("sc.filter", "XclImpDrawObjBase::CreateSdrObject, this control can't be set the property ControlTypeinMSO!");
491 if( mnObjType == 8 )//OCX
493 //Need summary type for export
494 static constexpr OUStringLiteral sObjIdPropertyName(u"ObjIDinMSO");
495 const XclImpPictureObj* const pObj = dynamic_cast< const XclImpPictureObj* const >(this);
496 if( pObj != nullptr && pObj->IsOcxControl() )
500 const sal_Int16 nOCXControlType = eCreateFromMSOCXControl;
501 xPropSet->setPropertyValue(sPropertyName, Any(nOCXControlType));
502 //Detail type(checkbox, button ...)
503 xPropSet->setPropertyValue(sObjIdPropertyName, makeAny<sal_uInt16>(mnObjId));
505 catch(const Exception&)
507 SAL_WARN("sc.filter", "XclImpDrawObjBase::CreateSdrObject, this control can't be set the property ObjIDinMSO!");
515 return xSdrObj;
518 void XclImpDrawObjBase::NotifyMacroEventRead()
520 if (mbNotifyMacroEventRead)
521 return;
522 SfxObjectShell* pDocShell = GetDocShell();
523 if (!pDocShell)
524 return;
525 comphelper::DocumentInfo::notifyMacroEventRead(pDocShell->GetModel());
526 mbNotifyMacroEventRead = true;
529 void XclImpDrawObjBase::PreProcessSdrObject( XclImpDffConverter& rDffConv, SdrObject& rSdrObj )
531 // default: front layer, derived classes may have to set other layer in DoPreProcessSdrObj()
532 rSdrObj.NbcSetLayer( SC_LAYER_FRONT );
534 // set object name (GetObjName() will always return a non-empty name)
535 rSdrObj.SetName( GetObjName() );
537 // #i39167# full width for all objects regardless of horizontal alignment
538 rSdrObj.SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_BLOCK ) );
540 // automatic text margin
541 if( mbAutoMargin )
543 sal_Int32 nMargin = rDffConv.GetDefaultTextMargin();
544 rSdrObj.SetMergedItem( makeSdrTextLeftDistItem( nMargin ) );
545 rSdrObj.SetMergedItem( makeSdrTextRightDistItem( nMargin ) );
546 rSdrObj.SetMergedItem( makeSdrTextUpperDistItem( nMargin ) );
547 rSdrObj.SetMergedItem( makeSdrTextLowerDistItem( nMargin ) );
550 // macro and hyperlink
551 // removed oracle/sun check for mbSimpleMacro ( no idea what its for )
552 if (!maMacroName.isEmpty())
554 if( ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( &rSdrObj, true ) )
556 OUString sMacro = XclTools::GetSbMacroUrl(maMacroName, GetDocShell());
557 if (!sMacro.isEmpty())
558 NotifyMacroEventRead();
559 pInfo->SetMacro(sMacro);
562 if (!maHyperlink.isEmpty())
563 rSdrObj.setHyperlink(maHyperlink);
565 // call virtual function for object type specific processing
566 DoPreProcessSdrObj( rDffConv, rSdrObj );
569 void XclImpDrawObjBase::PostProcessSdrObject( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const
571 // call virtual function for object type specific processing
572 DoPostProcessSdrObj( rDffConv, rSdrObj );
575 // protected ------------------------------------------------------------------
577 void XclImpDrawObjBase::ReadName5( XclImpStream& rStrm, sal_uInt16 nNameLen )
579 maObjName.clear();
580 if( nNameLen > 0 )
582 // name length field is repeated before the name
583 maObjName = rStrm.ReadByteString( false );
584 // skip padding byte for word boundaries
585 if( rStrm.GetRecPos() & 1 ) rStrm.Ignore( 1 );
589 void XclImpDrawObjBase::ReadMacro3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
591 maMacroName.clear();
592 rStrm.Ignore( nMacroSize );
593 // skip padding byte for word boundaries, not contained in nMacroSize
594 if( rStrm.GetRecPos() & 1 ) rStrm.Ignore( 1 );
597 void XclImpDrawObjBase::ReadMacro4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
599 maMacroName.clear();
600 rStrm.Ignore( nMacroSize );
603 void XclImpDrawObjBase::ReadMacro5( XclImpStream& rStrm, sal_uInt16 nMacroSize )
605 maMacroName.clear();
606 rStrm.Ignore( nMacroSize );
609 void XclImpDrawObjBase::ReadMacro8( XclImpStream& rStrm )
611 maMacroName.clear();
612 if( rStrm.GetRecLeft() <= 6 )
613 return;
615 // macro is stored in a tNameXR token containing a link to a defined name
616 sal_uInt16 nFmlaSize;
617 nFmlaSize = rStrm.ReaduInt16();
618 rStrm.Ignore( 4 );
619 OSL_ENSURE( nFmlaSize == 7, "XclImpDrawObjBase::ReadMacro - unexpected formula size" );
620 if( nFmlaSize == 7 )
622 sal_uInt8 nTokenId;
623 sal_uInt16 nExtSheet, nExtName;
624 nTokenId = rStrm.ReaduInt8();
625 nExtSheet = rStrm.ReaduInt16();
626 nExtName = rStrm.ReaduInt16();
627 OSL_ENSURE( nTokenId == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ),
628 "XclImpDrawObjBase::ReadMacro - tNameXR token expected" );
629 if( nTokenId == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ) )
630 maMacroName = GetLinkManager().GetMacroName( nExtSheet, nExtName );
634 void XclImpDrawObjBase::ConvertLineStyle( SdrObject& rSdrObj, const XclObjLineData& rLineData ) const
636 if( rLineData.IsAuto() )
638 XclObjLineData aAutoData;
639 aAutoData.mnAuto = 0;
640 ConvertLineStyle( rSdrObj, aAutoData );
642 else
644 tools::Long nLineWidth = 35 * ::std::min( rLineData.mnWidth, EXC_OBJ_LINE_THICK );
645 rSdrObj.SetMergedItem( XLineWidthItem( nLineWidth ) );
646 rSdrObj.SetMergedItem( XLineColorItem( OUString(), GetPalette().GetColor( rLineData.mnColorIdx ) ) );
647 rSdrObj.SetMergedItem( XLineJointItem( css::drawing::LineJoint_MITER ) );
649 sal_uLong nDotLen = ::std::max< sal_uLong >( 70 * rLineData.mnWidth, 35 );
650 sal_uLong nDashLen = 3 * nDotLen;
651 sal_uLong nDist = 2 * nDotLen;
653 switch( rLineData.mnStyle )
655 default:
656 case EXC_OBJ_LINE_SOLID:
657 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_SOLID ) );
658 break;
659 case EXC_OBJ_LINE_DASH:
660 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_DASH ) );
661 rSdrObj.SetMergedItem( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECT, 0, nDotLen, 1, nDashLen, nDist ) ) );
662 break;
663 case EXC_OBJ_LINE_DOT:
664 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_DASH ) );
665 rSdrObj.SetMergedItem( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECT, 1, nDotLen, 0, nDashLen, nDist ) ) );
666 break;
667 case EXC_OBJ_LINE_DASHDOT:
668 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_DASH ) );
669 rSdrObj.SetMergedItem( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECT, 1, nDotLen, 1, nDashLen, nDist ) ) );
670 break;
671 case EXC_OBJ_LINE_DASHDOTDOT:
672 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_DASH ) );
673 rSdrObj.SetMergedItem( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECT, 2, nDotLen, 1, nDashLen, nDist ) ) );
674 break;
675 case EXC_OBJ_LINE_MEDTRANS:
676 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_SOLID ) );
677 rSdrObj.SetMergedItem( XLineTransparenceItem( 50 ) );
678 break;
679 case EXC_OBJ_LINE_DARKTRANS:
680 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_SOLID ) );
681 rSdrObj.SetMergedItem( XLineTransparenceItem( 25 ) );
682 break;
683 case EXC_OBJ_LINE_LIGHTTRANS:
684 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_SOLID ) );
685 rSdrObj.SetMergedItem( XLineTransparenceItem( 75 ) );
686 break;
687 case EXC_OBJ_LINE_NONE:
688 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_NONE ) );
689 break;
694 void XclImpDrawObjBase::ConvertFillStyle( SdrObject& rSdrObj, const XclObjFillData& rFillData ) const
696 if( rFillData.IsAuto() )
698 XclObjFillData aAutoData;
699 aAutoData.mnAuto = 0;
700 ConvertFillStyle( rSdrObj, aAutoData );
702 else if( rFillData.mnPattern == EXC_PATT_NONE )
704 rSdrObj.SetMergedItem( XFillStyleItem( drawing::FillStyle_NONE ) );
706 else
708 Color aPattColor = GetPalette().GetColor( rFillData.mnPattColorIdx );
709 Color aBackColor = GetPalette().GetColor( rFillData.mnBackColorIdx );
710 if( (rFillData.mnPattern == EXC_PATT_SOLID) || (aPattColor == aBackColor) )
712 rSdrObj.SetMergedItem( XFillStyleItem( drawing::FillStyle_SOLID ) );
713 rSdrObj.SetMergedItem( XFillColorItem( OUString(), aPattColor ) );
715 else
717 static const sal_uInt8 sppnPatterns[][ 8 ] =
719 { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 },
720 { 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD },
721 { 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 },
722 { 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00 },
723 { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC },
724 { 0x33, 0x66, 0xCC, 0x99, 0x33, 0x66, 0xCC, 0x99 },
725 { 0xCC, 0x66, 0x33, 0x99, 0xCC, 0x66, 0x33, 0x99 },
726 { 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33 },
727 { 0xCC, 0xFF, 0x33, 0xFF, 0xCC, 0xFF, 0x33, 0xFF },
728 { 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 },
729 { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 },
730 { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 },
731 { 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 },
732 { 0xFF, 0x11, 0x11, 0x11, 0xFF, 0x11, 0x11, 0x11 },
733 { 0xAA, 0x44, 0xAA, 0x11, 0xAA, 0x44, 0xAA, 0x11 },
734 { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 },
735 { 0x80, 0x00, 0x08, 0x00, 0x80, 0x00, 0x08, 0x00 }
737 const sal_uInt8* const pnPattern = sppnPatterns[std::min<size_t>(rFillData.mnPattern - 2, SAL_N_ELEMENTS(sppnPatterns) - 1)];
738 // create 2-colored 8x8 DIB
739 SvMemoryStream aMemStrm;
740 aMemStrm.WriteUInt32( 12 ).WriteInt16( 8 ).WriteInt16( 8 ).WriteUInt16( 1 ).WriteUInt16( 1 );
741 aMemStrm.WriteUChar( 0xFF ).WriteUChar( 0xFF ).WriteUChar( 0xFF );
742 aMemStrm.WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x00 );
743 for( size_t nIdx = 0; nIdx < 8; ++nIdx )
744 aMemStrm.WriteUInt32( pnPattern[ nIdx ] ); // 32-bit little-endian
745 aMemStrm.Seek( STREAM_SEEK_TO_BEGIN );
746 Bitmap aBitmap;
747 (void)ReadDIB(aBitmap, aMemStrm, false);
749 XOBitmap aXOBitmap(( BitmapEx(aBitmap) ));
750 aXOBitmap.Bitmap2Array();
751 if( aXOBitmap.GetBackgroundColor() == COL_BLACK )
752 ::std::swap( aPattColor, aBackColor );
753 aXOBitmap.SetPixelColor( aPattColor );
754 aXOBitmap.SetBackgroundColor( aBackColor );
755 aXOBitmap.Array2Bitmap();
756 aBitmap = aXOBitmap.GetBitmap().GetBitmap();
758 rSdrObj.SetMergedItem(XFillStyleItem(drawing::FillStyle_BITMAP));
759 rSdrObj.SetMergedItem(XFillBitmapItem(OUString(), Graphic(BitmapEx(aBitmap))));
764 void XclImpDrawObjBase::ConvertFrameStyle( SdrObject& rSdrObj, sal_uInt16 nFrameFlags ) const
766 if( ::get_flag( nFrameFlags, EXC_OBJ_FRAME_SHADOW ) )
768 rSdrObj.SetMergedItem( makeSdrShadowItem( true ) );
769 rSdrObj.SetMergedItem( makeSdrShadowXDistItem( 35 ) );
770 rSdrObj.SetMergedItem( makeSdrShadowYDistItem( 35 ) );
771 rSdrObj.SetMergedItem( makeSdrShadowColorItem( GetPalette().GetColor( EXC_COLOR_WINDOWTEXT ) ) );
775 Color XclImpDrawObjBase::GetSolidLineColor( const XclObjLineData& rLineData ) const
777 Color aColor( COL_TRANSPARENT );
778 if( rLineData.IsAuto() )
780 XclObjLineData aAutoData;
781 aAutoData.mnAuto = 0;
782 aColor = GetSolidLineColor( aAutoData );
784 else if( rLineData.mnStyle != EXC_OBJ_LINE_NONE )
786 aColor = GetPalette().GetColor( rLineData.mnColorIdx );
788 return aColor;
791 Color XclImpDrawObjBase::GetSolidFillColor( const XclObjFillData& rFillData ) const
793 Color aColor( COL_TRANSPARENT );
794 if( rFillData.IsAuto() )
796 XclObjFillData aAutoData;
797 aAutoData.mnAuto = 0;
798 aColor = GetSolidFillColor( aAutoData );
800 else if( rFillData.mnPattern != EXC_PATT_NONE )
802 Color aPattColor = GetPalette().GetColor( rFillData.mnPattColorIdx );
803 Color aBackColor = GetPalette().GetColor( rFillData.mnBackColorIdx );
804 aColor = XclTools::GetPatternColor( aPattColor, aBackColor, rFillData.mnPattern );
806 return aColor;
809 void XclImpDrawObjBase::DoReadObj3( XclImpStream&, sal_uInt16 )
813 void XclImpDrawObjBase::DoReadObj4( XclImpStream&, sal_uInt16 )
817 void XclImpDrawObjBase::DoReadObj5( XclImpStream&, sal_uInt16, sal_uInt16 )
821 void XclImpDrawObjBase::DoReadObj8SubRec( XclImpStream&, sal_uInt16, sal_uInt16 )
825 std::size_t XclImpDrawObjBase::DoGetProgressSize() const
827 return 1;
830 SdrObjectUniquePtr XclImpDrawObjBase::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& ) const
832 rDffConv.Progress( GetProgressSize() );
833 return nullptr;
836 void XclImpDrawObjBase::DoPreProcessSdrObj( XclImpDffConverter&, SdrObject& ) const
838 // trace if object is not printable
839 if( !IsPrintable() )
840 GetTracer().TraceObjectNotPrintable();
843 void XclImpDrawObjBase::DoPostProcessSdrObj( XclImpDffConverter&, SdrObject& ) const
847 void XclImpDrawObjBase::ImplReadObj3( XclImpStream& rStrm )
849 // back to offset 4 (ignore object count field)
850 rStrm.Seek( 4 );
852 sal_uInt16 nObjFlags, nMacroSize;
853 mnObjType = rStrm.ReaduInt16();
854 mnObjId = rStrm.ReaduInt16();
855 nObjFlags = rStrm.ReaduInt16();
856 rStrm >> maAnchor;
857 nMacroSize = rStrm.ReaduInt16();
858 rStrm.Ignore( 2 );
860 mbHasAnchor = true;
861 mbHidden = ::get_flag( nObjFlags, EXC_OBJ_HIDDEN );
862 mbVisible = ::get_flag( nObjFlags, EXC_OBJ_VISIBLE );
863 DoReadObj3( rStrm, nMacroSize );
866 void XclImpDrawObjBase::ImplReadObj4( XclImpStream& rStrm )
868 // back to offset 4 (ignore object count field)
869 rStrm.Seek( 4 );
871 sal_uInt16 nObjFlags, nMacroSize;
872 mnObjType = rStrm.ReaduInt16();
873 mnObjId = rStrm.ReaduInt16();
874 nObjFlags = rStrm.ReaduInt16();
875 rStrm >> maAnchor;
876 nMacroSize = rStrm.ReaduInt16();
877 rStrm.Ignore( 2 );
879 mbHasAnchor = true;
880 mbHidden = ::get_flag( nObjFlags, EXC_OBJ_HIDDEN );
881 mbVisible = ::get_flag( nObjFlags, EXC_OBJ_VISIBLE );
882 mbPrintable = ::get_flag( nObjFlags, EXC_OBJ_PRINTABLE );
883 DoReadObj4( rStrm, nMacroSize );
886 void XclImpDrawObjBase::ImplReadObj5( XclImpStream& rStrm )
888 // back to offset 4 (ignore object count field)
889 rStrm.Seek( 4 );
891 sal_uInt16 nObjFlags, nMacroSize, nNameLen;
892 mnObjType = rStrm.ReaduInt16();
893 mnObjId = rStrm.ReaduInt16();
894 nObjFlags = rStrm.ReaduInt16();
895 rStrm >> maAnchor;
896 nMacroSize = rStrm.ReaduInt16();
897 rStrm.Ignore( 2 );
898 nNameLen = rStrm.ReaduInt16();
899 rStrm.Ignore( 2 );
901 mbHasAnchor = true;
902 mbHidden = ::get_flag( nObjFlags, EXC_OBJ_HIDDEN );
903 mbVisible = ::get_flag( nObjFlags, EXC_OBJ_VISIBLE );
904 mbPrintable = ::get_flag( nObjFlags, EXC_OBJ_PRINTABLE );
905 DoReadObj5( rStrm, nNameLen, nMacroSize );
908 void XclImpDrawObjBase::ImplReadObj8( XclImpStream& rStrm )
910 // back to beginning
911 rStrm.Seek( EXC_REC_SEEK_TO_BEGIN );
913 bool bLoop = true;
914 while (bLoop)
916 if (rStrm.GetRecLeft() < 4)
917 break;
919 sal_uInt16 nSubRecId = rStrm.ReaduInt16();
920 sal_uInt16 nSubRecSize = rStrm.ReaduInt16();
921 rStrm.PushPosition();
922 // sometimes the last subrecord has an invalid length (OBJLBSDATA) -> min()
923 nSubRecSize = static_cast< sal_uInt16 >( ::std::min< std::size_t >( nSubRecSize, rStrm.GetRecLeft() ) );
925 switch( nSubRecId )
927 case EXC_ID_OBJCMO:
928 OSL_ENSURE( rStrm.GetRecPos() == 4, "XclImpDrawObjBase::ImplReadObj8 - unexpected OBJCMO subrecord" );
929 if( (rStrm.GetRecPos() == 4) && (nSubRecSize >= 6) )
931 sal_uInt16 nObjFlags;
932 mnObjType = rStrm.ReaduInt16();
933 mnObjId = rStrm.ReaduInt16( );
934 nObjFlags = rStrm.ReaduInt16( );
935 mbPrintable = ::get_flag( nObjFlags, EXC_OBJCMO_PRINTABLE );
937 break;
938 case EXC_ID_OBJMACRO:
939 ReadMacro8( rStrm );
940 break;
941 case EXC_ID_OBJEND:
942 bLoop = false;
943 break;
944 default:
945 DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
948 rStrm.PopPosition();
949 rStrm.Ignore( nSubRecSize );
952 /* Call DoReadObj8SubRec() with EXC_ID_OBJEND for further stream
953 processing (e.g. charts), even if the OBJEND subrecord is missing. */
954 DoReadObj8SubRec( rStrm, EXC_ID_OBJEND, 0 );
956 /* Pictures that Excel reads from BIFF5 and writes to BIFF8 still have the
957 IMGDATA record following the OBJ record (but they use the image data
958 stored in DFF). The IMGDATA record may be continued by several CONTINUE
959 records. But the last CONTINUE record may be in fact an MSODRAWING
960 record that contains the DFF data of the next drawing object! So we
961 have to skip just enough CONTINUE records to look at the next
962 MSODRAWING/CONTINUE record. */
963 if( !((rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord()) )
964 return;
966 rStrm.Ignore( 4 );
967 sal_uInt32 nDataSize = rStrm.ReaduInt32();
968 nDataSize -= rStrm.GetRecLeft();
969 // skip following CONTINUE records until IMGDATA ends
970 while (true)
972 if (!nDataSize)
973 break;
974 if (rStrm.GetNextRecId() != EXC_ID_CONT)
975 break;
976 if (!rStrm.StartNextRecord())
977 break;
978 OSL_ENSURE( nDataSize >= rStrm.GetRecLeft(), "XclImpDrawObjBase::ImplReadObj8 - CONTINUE too long" );
979 nDataSize -= ::std::min< sal_uInt32 >( rStrm.GetRecLeft(), nDataSize );
981 OSL_ENSURE( nDataSize == 0, "XclImpDrawObjBase::ImplReadObj8 - missing CONTINUE records" );
982 // next record may be MSODRAWING or CONTINUE or anything else
985 void XclImpDrawObjVector::InsertGrouped( XclImpDrawObjRef const & xDrawObj )
987 if( !mObjs.empty() )
988 if( XclImpGroupObj* pGroupObj = dynamic_cast< XclImpGroupObj* >( mObjs.back().get() ) )
989 if( pGroupObj->TryInsert( xDrawObj ) )
990 return;
991 mObjs.push_back( xDrawObj );
994 std::size_t XclImpDrawObjVector::GetProgressSize() const
996 return std::accumulate(mObjs.begin(), mObjs.end(), std::size_t(0),
997 [](const std::size_t& rSum, const XclImpDrawObjRef& rxObj) { return rSum + rxObj->GetProgressSize(); });
1000 XclImpPhObj::XclImpPhObj( const XclImpRoot& rRoot ) :
1001 XclImpDrawObjBase( rRoot )
1003 SetProcessSdrObj( false );
1006 XclImpGroupObj::XclImpGroupObj( const XclImpRoot& rRoot ) :
1007 XclImpDrawObjBase( rRoot ),
1008 mnFirstUngrouped( 0 )
1012 bool XclImpGroupObj::TryInsert( XclImpDrawObjRef const & xDrawObj )
1014 if( xDrawObj->GetObjId() == mnFirstUngrouped )
1015 return false;
1016 // insert into own list or into nested group
1017 maChildren.InsertGrouped( xDrawObj );
1018 return true;
1021 void XclImpGroupObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1023 rStrm.Ignore( 4 );
1024 mnFirstUngrouped = rStrm.ReaduInt16();
1025 rStrm.Ignore( 16 );
1026 ReadMacro3( rStrm, nMacroSize );
1029 void XclImpGroupObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1031 rStrm.Ignore( 4 );
1032 mnFirstUngrouped = rStrm.ReaduInt16();
1033 rStrm.Ignore( 16 );
1034 ReadMacro4( rStrm, nMacroSize );
1037 void XclImpGroupObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1039 rStrm.Ignore( 4 );
1040 mnFirstUngrouped = rStrm.ReaduInt16();
1041 rStrm.Ignore( 16 );
1042 ReadName5( rStrm, nNameLen );
1043 ReadMacro5( rStrm, nMacroSize );
1046 std::size_t XclImpGroupObj::DoGetProgressSize() const
1048 return XclImpDrawObjBase::DoGetProgressSize() + maChildren.GetProgressSize();
1051 SdrObjectUniquePtr XclImpGroupObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& /*rAnchorRect*/ ) const
1053 std::unique_ptr<SdrObjGroup, SdrObjectFreeOp> xSdrObj(
1054 new SdrObjGroup(
1055 *GetDoc().GetDrawLayer()));
1056 // child objects in BIFF2-BIFF5 have absolute size, not needed to pass own anchor rectangle
1057 SdrObjList& rObjList = *xSdrObj->GetSubList(); // SdrObjGroup always returns existing sublist
1058 for( const auto& rxChild : maChildren )
1059 rDffConv.ProcessObject( rObjList, *rxChild );
1060 rDffConv.Progress();
1061 return xSdrObj;
1064 XclImpLineObj::XclImpLineObj( const XclImpRoot& rRoot ) :
1065 XclImpDrawObjBase( rRoot ),
1066 mnArrows( 0 ),
1067 mnStartPoint( EXC_OBJ_LINE_TL )
1069 SetAreaObj( false );
1072 void XclImpLineObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1074 rStrm >> maLineData;
1075 mnArrows = rStrm.ReaduInt16();
1076 mnStartPoint = rStrm.ReaduInt8();
1077 rStrm.Ignore( 1 );
1078 ReadMacro3( rStrm, nMacroSize );
1081 void XclImpLineObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1083 rStrm >> maLineData;
1084 mnArrows = rStrm.ReaduInt16();
1085 mnStartPoint = rStrm.ReaduInt8();
1086 rStrm.Ignore( 1 );
1087 ReadMacro4( rStrm, nMacroSize );
1090 void XclImpLineObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1092 rStrm >> maLineData;
1093 mnArrows = rStrm.ReaduInt16();
1094 mnStartPoint = rStrm.ReaduInt8();
1095 rStrm.Ignore( 1 );
1096 ReadName5( rStrm, nNameLen );
1097 ReadMacro5( rStrm, nMacroSize );
1100 SdrObjectUniquePtr XclImpLineObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1102 ::basegfx::B2DPolygon aB2DPolygon;
1103 switch( mnStartPoint )
1105 default:
1106 case EXC_OBJ_LINE_TL:
1107 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Top() ) );
1108 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Bottom() ) );
1109 break;
1110 case EXC_OBJ_LINE_TR:
1111 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Top() ) );
1112 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Bottom() ) );
1113 break;
1114 case EXC_OBJ_LINE_BR:
1115 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Bottom() ) );
1116 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Top() ) );
1117 break;
1118 case EXC_OBJ_LINE_BL:
1119 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Bottom() ) );
1120 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Top() ) );
1121 break;
1123 SdrObjectUniquePtr xSdrObj(
1124 new SdrPathObj(
1125 *GetDoc().GetDrawLayer(),
1126 OBJ_LINE,
1127 ::basegfx::B2DPolyPolygon(aB2DPolygon)));
1128 ConvertLineStyle( *xSdrObj, maLineData );
1130 // line ends
1131 sal_uInt8 nArrowType = ::extract_value< sal_uInt8 >( mnArrows, 0, 4 );
1132 bool bLineStart = false;
1133 bool bLineEnd = false;
1134 bool bFilled = false;
1135 switch( nArrowType )
1137 case EXC_OBJ_ARROW_OPEN: bLineStart = false; bLineEnd = true; bFilled = false; break;
1138 case EXC_OBJ_ARROW_OPENBOTH: bLineStart = true; bLineEnd = true; bFilled = false; break;
1139 case EXC_OBJ_ARROW_FILLED: bLineStart = false; bLineEnd = true; bFilled = true; break;
1140 case EXC_OBJ_ARROW_FILLEDBOTH: bLineStart = true; bLineEnd = true; bFilled = true; break;
1142 if( bLineStart || bLineEnd )
1144 sal_uInt8 nArrowWidth = ::extract_value< sal_uInt8 >( mnArrows, 4, 4 );
1145 double fArrowWidth = 3.0;
1146 switch( nArrowWidth )
1148 case EXC_OBJ_ARROW_NARROW: fArrowWidth = 2.0; break;
1149 case EXC_OBJ_ARROW_MEDIUM: fArrowWidth = 3.0; break;
1150 case EXC_OBJ_ARROW_WIDE: fArrowWidth = 5.0; break;
1153 sal_uInt8 nArrowLength = ::extract_value< sal_uInt8 >( mnArrows, 8, 4 );
1154 double fArrowLength = 3.0;
1155 switch( nArrowLength )
1157 case EXC_OBJ_ARROW_NARROW: fArrowLength = 2.5; break;
1158 case EXC_OBJ_ARROW_MEDIUM: fArrowLength = 3.5; break;
1159 case EXC_OBJ_ARROW_WIDE: fArrowLength = 6.0; break;
1162 ::basegfx::B2DPolygon aArrowPoly;
1163 #define EXC_ARROW_POINT( x, y ) ::basegfx::B2DPoint( fArrowWidth * (x), fArrowLength * (y) )
1164 if( bFilled )
1166 aArrowPoly.append( EXC_ARROW_POINT( 0, 100 ) );
1167 aArrowPoly.append( EXC_ARROW_POINT( 50, 0 ) );
1168 aArrowPoly.append( EXC_ARROW_POINT( 100, 100 ) );
1170 else
1172 sal_uInt8 nLineWidth = ::limit_cast< sal_uInt8 >( maLineData.mnWidth, EXC_OBJ_LINE_THIN, EXC_OBJ_LINE_THICK );
1173 aArrowPoly.append( EXC_ARROW_POINT( 50, 0 ) );
1174 aArrowPoly.append( EXC_ARROW_POINT( 100, 100 - 3 * nLineWidth ) );
1175 aArrowPoly.append( EXC_ARROW_POINT( 100 - 5 * nLineWidth, 100 ) );
1176 aArrowPoly.append( EXC_ARROW_POINT( 50, 12 * nLineWidth ) );
1177 aArrowPoly.append( EXC_ARROW_POINT( 5 * nLineWidth, 100 ) );
1178 aArrowPoly.append( EXC_ARROW_POINT( 0, 100 - 3 * nLineWidth ) );
1180 #undef EXC_ARROW_POINT
1182 ::basegfx::B2DPolyPolygon aArrowPolyPoly( aArrowPoly );
1183 tools::Long nWidth = static_cast< tools::Long >( 125 * fArrowWidth );
1184 if( bLineStart )
1186 xSdrObj->SetMergedItem( XLineStartItem( OUString(), aArrowPolyPoly ) );
1187 xSdrObj->SetMergedItem( XLineStartWidthItem( nWidth ) );
1188 xSdrObj->SetMergedItem( XLineStartCenterItem( false ) );
1190 if( bLineEnd )
1192 xSdrObj->SetMergedItem( XLineEndItem( OUString(), aArrowPolyPoly ) );
1193 xSdrObj->SetMergedItem( XLineEndWidthItem( nWidth ) );
1194 xSdrObj->SetMergedItem( XLineEndCenterItem( false ) );
1197 rDffConv.Progress();
1198 return xSdrObj;
1201 XclImpRectObj::XclImpRectObj( const XclImpRoot& rRoot ) :
1202 XclImpDrawObjBase( rRoot ),
1203 mnFrameFlags( 0 )
1205 SetAreaObj( true );
1208 void XclImpRectObj::ReadFrameData( XclImpStream& rStrm )
1210 rStrm >> maFillData >> maLineData;
1211 mnFrameFlags = rStrm.ReaduInt16();
1214 void XclImpRectObj::ConvertRectStyle( SdrObject& rSdrObj ) const
1216 ConvertLineStyle( rSdrObj, maLineData );
1217 ConvertFillStyle( rSdrObj, maFillData );
1218 ConvertFrameStyle( rSdrObj, mnFrameFlags );
1221 void XclImpRectObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1223 ReadFrameData( rStrm );
1224 ReadMacro3( rStrm, nMacroSize );
1227 void XclImpRectObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1229 ReadFrameData( rStrm );
1230 ReadMacro4( rStrm, nMacroSize );
1233 void XclImpRectObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1235 ReadFrameData( rStrm );
1236 ReadName5( rStrm, nNameLen );
1237 ReadMacro5( rStrm, nMacroSize );
1240 SdrObjectUniquePtr XclImpRectObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1242 SdrObjectUniquePtr xSdrObj(
1243 new SdrRectObj(
1244 *GetDoc().GetDrawLayer(),
1245 rAnchorRect));
1246 ConvertRectStyle( *xSdrObj );
1247 rDffConv.Progress();
1248 return xSdrObj;
1251 XclImpOvalObj::XclImpOvalObj( const XclImpRoot& rRoot ) :
1252 XclImpRectObj( rRoot )
1256 SdrObjectUniquePtr XclImpOvalObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1258 SdrObjectUniquePtr xSdrObj(
1259 new SdrCircObj(
1260 *GetDoc().GetDrawLayer(),
1261 SdrCircKind::Full,
1262 rAnchorRect));
1263 ConvertRectStyle( *xSdrObj );
1264 rDffConv.Progress();
1265 return xSdrObj;
1268 XclImpArcObj::XclImpArcObj( const XclImpRoot& rRoot ) :
1269 XclImpDrawObjBase( rRoot ),
1270 mnQuadrant( EXC_OBJ_ARC_TR )
1272 SetAreaObj( false ); // arc may be 2-dimensional
1275 void XclImpArcObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1277 rStrm >> maFillData >> maLineData;
1278 mnQuadrant = rStrm.ReaduInt8();
1279 rStrm.Ignore( 1 );
1280 ReadMacro3( rStrm, nMacroSize );
1283 void XclImpArcObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1285 rStrm >> maFillData >> maLineData;
1286 mnQuadrant = rStrm.ReaduInt8();
1287 rStrm.Ignore( 1 );
1288 ReadMacro4( rStrm, nMacroSize );
1291 void XclImpArcObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1293 rStrm >> maFillData >> maLineData;
1294 mnQuadrant = rStrm.ReaduInt8();
1295 rStrm.Ignore( 1 );
1296 ReadName5( rStrm, nNameLen );
1297 ReadMacro5( rStrm, nMacroSize );
1300 SdrObjectUniquePtr XclImpArcObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1302 tools::Rectangle aNewRect = rAnchorRect;
1303 Degree100 nStartAngle;
1304 Degree100 nEndAngle;
1305 switch( mnQuadrant )
1307 default:
1308 case EXC_OBJ_ARC_TR:
1309 nStartAngle = 0_deg100;
1310 nEndAngle = 9000_deg100;
1311 aNewRect.AdjustLeft( -(rAnchorRect.GetWidth()) );
1312 aNewRect.AdjustBottom(rAnchorRect.GetHeight() );
1313 break;
1314 case EXC_OBJ_ARC_TL:
1315 nStartAngle = 9000_deg100;
1316 nEndAngle = 18000_deg100;
1317 aNewRect.AdjustRight(rAnchorRect.GetWidth() );
1318 aNewRect.AdjustBottom(rAnchorRect.GetHeight() );
1319 break;
1320 case EXC_OBJ_ARC_BL:
1321 nStartAngle = 18000_deg100;
1322 nEndAngle = 27000_deg100;
1323 aNewRect.AdjustRight(rAnchorRect.GetWidth() );
1324 aNewRect.AdjustTop( -(rAnchorRect.GetHeight()) );
1325 break;
1326 case EXC_OBJ_ARC_BR:
1327 nStartAngle = 27000_deg100;
1328 nEndAngle = 0_deg100;
1329 aNewRect.AdjustLeft( -(rAnchorRect.GetWidth()) );
1330 aNewRect.AdjustTop( -(rAnchorRect.GetHeight()) );
1331 break;
1333 SdrCircKind eObjKind = maFillData.IsFilled() ? SdrCircKind::Section : SdrCircKind::Arc;
1334 SdrObjectUniquePtr xSdrObj(
1335 new SdrCircObj(
1336 *GetDoc().GetDrawLayer(),
1337 eObjKind,
1338 aNewRect,
1339 nStartAngle,
1340 nEndAngle));
1341 ConvertFillStyle( *xSdrObj, maFillData );
1342 ConvertLineStyle( *xSdrObj, maLineData );
1343 rDffConv.Progress();
1344 return xSdrObj;
1347 XclImpPolygonObj::XclImpPolygonObj( const XclImpRoot& rRoot ) :
1348 XclImpRectObj( rRoot ),
1349 mnPolyFlags( 0 ),
1350 mnPointCount( 0 )
1352 SetAreaObj( false ); // polygon may be 2-dimensional
1355 void XclImpPolygonObj::ReadCoordList( XclImpStream& rStrm )
1357 if( (rStrm.GetNextRecId() == EXC_ID_COORDLIST) && rStrm.StartNextRecord() )
1359 OSL_ENSURE( rStrm.GetRecLeft() / 4 == mnPointCount, "XclImpPolygonObj::ReadCoordList - wrong polygon point count" );
1360 while (true)
1362 if (rStrm.GetRecLeft() < 4)
1363 break;
1364 sal_uInt16 nX = rStrm.ReaduInt16();
1365 sal_uInt16 nY = rStrm.ReaduInt16();
1366 maCoords.emplace_back( nX, nY );
1371 void XclImpPolygonObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1373 ReadFrameData( rStrm );
1374 mnPolyFlags = rStrm.ReaduInt16();
1375 rStrm.Ignore( 10 );
1376 mnPointCount = rStrm.ReaduInt16();
1377 rStrm.Ignore( 8 );
1378 ReadMacro4( rStrm, nMacroSize );
1379 ReadCoordList( rStrm );
1382 void XclImpPolygonObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1384 ReadFrameData( rStrm );
1385 mnPolyFlags = rStrm.ReaduInt16();
1386 rStrm.Ignore( 10 );
1387 mnPointCount = rStrm.ReaduInt16();
1388 rStrm.Ignore( 8 );
1389 ReadName5( rStrm, nNameLen );
1390 ReadMacro5( rStrm, nMacroSize );
1391 ReadCoordList( rStrm );
1394 namespace {
1396 ::basegfx::B2DPoint lclGetPolyPoint( const tools::Rectangle& rAnchorRect, const Point& rPoint )
1398 return ::basegfx::B2DPoint(
1399 rAnchorRect.Left() + static_cast< sal_Int32 >( ::std::min< double >( rPoint.X(), 16384.0 ) / 16384.0 * rAnchorRect.GetWidth() + 0.5 ),
1400 rAnchorRect.Top() + static_cast< sal_Int32 >( ::std::min< double >( rPoint.Y(), 16384.0 ) / 16384.0 * rAnchorRect.GetHeight() + 0.5 ) );
1403 } // namespace
1405 SdrObjectUniquePtr XclImpPolygonObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1407 SdrObjectUniquePtr xSdrObj;
1408 if( maCoords.size() >= 2 )
1410 // create the polygon
1411 ::basegfx::B2DPolygon aB2DPolygon;
1412 for( const auto& rCoord : maCoords )
1413 aB2DPolygon.append( lclGetPolyPoint( rAnchorRect, rCoord ) );
1414 // close polygon if specified
1415 if( ::get_flag( mnPolyFlags, EXC_OBJ_POLY_CLOSED ) && (maCoords.front() != maCoords.back()) )
1416 aB2DPolygon.append( lclGetPolyPoint( rAnchorRect, maCoords.front() ) );
1417 // create the SdrObject
1418 SdrObjKind eObjKind = maFillData.IsFilled() ? OBJ_PATHPOLY : OBJ_PATHPLIN;
1419 xSdrObj.reset(
1420 new SdrPathObj(
1421 *GetDoc().GetDrawLayer(),
1422 eObjKind,
1423 ::basegfx::B2DPolyPolygon(aB2DPolygon)));
1424 ConvertRectStyle( *xSdrObj );
1426 rDffConv.Progress();
1427 return xSdrObj;
1430 void XclImpObjTextData::ReadByteString( XclImpStream& rStrm )
1432 mxString.reset();
1433 if( maData.mnTextLen > 0 )
1435 mxString = std::make_shared<XclImpString>( rStrm.ReadRawByteString( maData.mnTextLen ) );
1436 // skip padding byte for word boundaries
1437 if( rStrm.GetRecPos() & 1 ) rStrm.Ignore( 1 );
1441 void XclImpObjTextData::ReadFormats( XclImpStream& rStrm )
1443 if( mxString )
1444 mxString->ReadObjFormats( rStrm, maData.mnFormatSize );
1445 else
1446 rStrm.Ignore( maData.mnFormatSize );
1449 XclImpTextObj::XclImpTextObj( const XclImpRoot& rRoot ) :
1450 XclImpRectObj( rRoot )
1454 void XclImpTextObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1456 ReadFrameData( rStrm );
1457 maTextData.maData.ReadObj3( rStrm );
1458 ReadMacro3( rStrm, nMacroSize );
1459 maTextData.ReadByteString( rStrm );
1460 maTextData.ReadFormats( rStrm );
1463 void XclImpTextObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1465 ReadFrameData( rStrm );
1466 maTextData.maData.ReadObj3( rStrm );
1467 ReadMacro4( rStrm, nMacroSize );
1468 maTextData.ReadByteString( rStrm );
1469 maTextData.ReadFormats( rStrm );
1472 void XclImpTextObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1474 ReadFrameData( rStrm );
1475 maTextData.maData.ReadObj5( rStrm );
1476 ReadName5( rStrm, nNameLen );
1477 ReadMacro5( rStrm, nMacroSize );
1478 maTextData.ReadByteString( rStrm );
1479 rStrm.Ignore( maTextData.maData.mnLinkSize ); // ignore text link formula
1480 maTextData.ReadFormats( rStrm );
1483 SdrObjectUniquePtr XclImpTextObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1485 std::unique_ptr<SdrObjCustomShape, SdrObjectFreeOp> xSdrObj(
1486 new SdrObjCustomShape(
1487 *GetDoc().GetDrawLayer()));
1488 xSdrObj->NbcSetSnapRect( rAnchorRect );
1489 OUString aRectType = "rectangle";
1490 xSdrObj->MergeDefaultAttributes( &aRectType );
1491 ConvertRectStyle( *xSdrObj );
1492 bool bAutoSize = ::get_flag( maTextData.maData.mnFlags, EXC_OBJ_TEXT_AUTOSIZE );
1493 xSdrObj->SetMergedItem( makeSdrTextAutoGrowWidthItem( bAutoSize ) );
1494 xSdrObj->SetMergedItem( makeSdrTextAutoGrowHeightItem( bAutoSize ) );
1495 xSdrObj->SetMergedItem( makeSdrTextWordWrapItem( true ) );
1496 rDffConv.Progress();
1497 return xSdrObj;
1500 void XclImpTextObj::DoPreProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const
1502 // set text data
1503 if( SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( &rSdrObj ) )
1505 if( maTextData.mxString )
1507 if( maTextData.mxString->IsRich() )
1509 if (maTextData.mxString->GetText().getLength() > 1024 && utl::ConfigManager::IsFuzzing())
1511 SAL_WARN("sc.filter", "truncating slow long rich text for fuzzing performance");
1512 maTextData.mxString->SetText(maTextData.mxString->GetText().copy(0, 1024));
1515 // rich text
1516 std::unique_ptr< EditTextObject > xEditObj(
1517 XclImpStringHelper::CreateTextObject( GetRoot(), *maTextData.mxString ) );
1518 OutlinerParaObject aOutlineObj(std::move(xEditObj));
1519 aOutlineObj.SetOutlinerMode( OutlinerMode::TextObject );
1520 pTextObj->NbcSetOutlinerParaObject( std::move(aOutlineObj) );
1522 else
1524 // plain text
1525 pTextObj->NbcSetText( maTextData.mxString->GetText() );
1528 /* #i96858# Do not apply any formatting if there is no text.
1529 SdrObjCustomShape::SetVerticalWriting (initiated from
1530 SetMergedItem) calls SdrTextObj::ForceOutlinerParaObject which
1531 ensures that we can erroneously write a ClientTextbox record
1532 (with no content) while exporting to XLS, which can cause a
1533 corrupted exported document. */
1535 SvxAdjust eHorAlign = SvxAdjust::Left;
1536 SdrTextVertAdjust eVerAlign = SDRTEXTVERTADJUST_TOP;
1538 // orientation (this is only a fake, drawing does not support real text orientation)
1539 namespace csst = ::com::sun::star::text;
1540 csst::WritingMode eWriteMode = csst::WritingMode_LR_TB;
1541 switch( maTextData.maData.mnOrient )
1543 default:
1544 case EXC_OBJ_ORIENT_NONE:
1546 eWriteMode = csst::WritingMode_LR_TB;
1547 switch( maTextData.maData.GetHorAlign() )
1549 case EXC_OBJ_HOR_LEFT: eHorAlign = SvxAdjust::Left; break;
1550 case EXC_OBJ_HOR_CENTER: eHorAlign = SvxAdjust::Center; break;
1551 case EXC_OBJ_HOR_RIGHT: eHorAlign = SvxAdjust::Right; break;
1552 case EXC_OBJ_HOR_JUSTIFY: eHorAlign = SvxAdjust::Block; break;
1554 switch( maTextData.maData.GetVerAlign() )
1556 case EXC_OBJ_VER_TOP: eVerAlign = SDRTEXTVERTADJUST_TOP; break;
1557 case EXC_OBJ_VER_CENTER: eVerAlign = SDRTEXTVERTADJUST_CENTER; break;
1558 case EXC_OBJ_VER_BOTTOM: eVerAlign = SDRTEXTVERTADJUST_BOTTOM; break;
1559 case EXC_OBJ_VER_JUSTIFY: eVerAlign = SDRTEXTVERTADJUST_BLOCK; break;
1562 break;
1564 case EXC_OBJ_ORIENT_90CCW:
1566 if( SdrObjCustomShape* pObjCustomShape = dynamic_cast< SdrObjCustomShape* >( &rSdrObj ) )
1568 css::beans::PropertyValue aTextRotateAngle;
1569 aTextRotateAngle.Name = "TextRotateAngle";
1570 aTextRotateAngle.Value <<= 180.0;
1571 SdrCustomShapeGeometryItem aGeometryItem(pObjCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ));
1572 aGeometryItem.SetPropertyValue( aTextRotateAngle );
1573 pObjCustomShape->SetMergedItem( aGeometryItem );
1575 eWriteMode = csst::WritingMode_TB_RL;
1576 switch( maTextData.maData.GetHorAlign() )
1578 case EXC_OBJ_HOR_LEFT: eVerAlign = SDRTEXTVERTADJUST_TOP; break;
1579 case EXC_OBJ_HOR_CENTER: eVerAlign = SDRTEXTVERTADJUST_CENTER; break;
1580 case EXC_OBJ_HOR_RIGHT: eVerAlign = SDRTEXTVERTADJUST_BOTTOM; break;
1581 case EXC_OBJ_HOR_JUSTIFY: eVerAlign = SDRTEXTVERTADJUST_BLOCK; break;
1583 MSO_Anchor eTextAnchor = static_cast<MSO_Anchor>(rDffConv.GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop ));
1584 switch( eTextAnchor )
1586 case mso_anchorTopCentered :
1587 case mso_anchorMiddleCentered :
1588 case mso_anchorBottomCentered :
1590 eHorAlign = SvxAdjust::Center;
1592 break;
1594 default:
1596 switch( maTextData.maData.GetVerAlign() )
1598 case EXC_OBJ_VER_TOP: eHorAlign = SvxAdjust::Right; break;
1599 case EXC_OBJ_VER_CENTER: eHorAlign = SvxAdjust::Center; break;
1600 case EXC_OBJ_VER_BOTTOM: eHorAlign = SvxAdjust::Left; break;
1601 case EXC_OBJ_VER_JUSTIFY: eHorAlign = SvxAdjust::Block; break;
1606 break;
1608 case EXC_OBJ_ORIENT_STACKED:
1610 // sj: STACKED is not supported, maybe it can be optimized here a bit
1611 [[fallthrough]];
1613 case EXC_OBJ_ORIENT_90CW:
1615 eWriteMode = csst::WritingMode_TB_RL;
1616 switch( maTextData.maData.GetHorAlign() )
1618 case EXC_OBJ_HOR_LEFT: eVerAlign = SDRTEXTVERTADJUST_BOTTOM; break;
1619 case EXC_OBJ_HOR_CENTER: eVerAlign = SDRTEXTVERTADJUST_CENTER; break;
1620 case EXC_OBJ_HOR_RIGHT: eVerAlign = SDRTEXTVERTADJUST_TOP; break;
1621 case EXC_OBJ_HOR_JUSTIFY: eVerAlign = SDRTEXTVERTADJUST_BLOCK; break;
1623 MSO_Anchor eTextAnchor = static_cast<MSO_Anchor>(rDffConv.GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop ));
1624 switch ( eTextAnchor )
1626 case mso_anchorTopCentered :
1627 case mso_anchorMiddleCentered :
1628 case mso_anchorBottomCentered :
1630 eHorAlign = SvxAdjust::Center;
1632 break;
1634 default:
1636 switch( maTextData.maData.GetVerAlign() )
1638 case EXC_OBJ_VER_TOP: eHorAlign = SvxAdjust::Left; break;
1639 case EXC_OBJ_VER_CENTER: eHorAlign = SvxAdjust::Center; break;
1640 case EXC_OBJ_VER_BOTTOM: eHorAlign = SvxAdjust::Right; break;
1641 case EXC_OBJ_VER_JUSTIFY: eHorAlign = SvxAdjust::Block; break;
1646 break;
1648 rSdrObj.SetMergedItem( SvxAdjustItem( eHorAlign, EE_PARA_JUST ) );
1649 rSdrObj.SetMergedItem( SdrTextVertAdjustItem( eVerAlign ) );
1650 rSdrObj.SetMergedItem( SvxWritingModeItem( eWriteMode, SDRATTR_TEXTDIRECTION ) );
1653 // base class processing
1654 XclImpRectObj::DoPreProcessSdrObj( rDffConv, rSdrObj );
1657 XclImpChartObj::XclImpChartObj( const XclImpRoot& rRoot, bool bOwnTab ) :
1658 XclImpRectObj( rRoot ),
1659 mbOwnTab( bOwnTab )
1661 SetSimpleMacro( false );
1662 SetCustomDffObj( true );
1665 void XclImpChartObj::ReadChartSubStream( XclImpStream& rStrm )
1667 /* If chart is read from a chartsheet (mbOwnTab == true), the BOF record
1668 has already been read. If chart is embedded as object, the next record
1669 has to be the BOF record. */
1670 if( mbOwnTab )
1672 /* #i109800# The input stream may point somewhere inside the chart
1673 substream and not exactly to the leading BOF record. To read this
1674 record correctly in the following, the stream has to rewind it, so
1675 that the next call to StartNextRecord() will find it correctly. */
1676 if( rStrm.GetRecId() != EXC_ID5_BOF )
1677 rStrm.RewindRecord();
1679 else
1681 if( (rStrm.GetNextRecId() == EXC_ID5_BOF) && rStrm.StartNextRecord() )
1683 sal_uInt16 nBofType;
1684 rStrm.Seek( 2 );
1685 nBofType = rStrm.ReaduInt16();
1686 SAL_WARN_IF( nBofType != EXC_BOF_CHART, "sc.filter", "XclImpChartObj::ReadChartSubStream - no chart BOF record" );
1688 else
1690 SAL_INFO("sc.filter", "XclImpChartObj::ReadChartSubStream - missing chart substream");
1691 return;
1695 // read chart, even if BOF record contains wrong substream identifier
1696 mxChart = std::make_shared<XclImpChart>( GetRoot(), mbOwnTab );
1697 mxChart->ReadChartSubStream( rStrm );
1698 if( mbOwnTab )
1699 FinalizeTabChart();
1702 void XclImpChartObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1704 // read OBJ record and the following chart substream
1705 ReadFrameData( rStrm );
1706 rStrm.Ignore( 18 );
1707 ReadMacro3( rStrm, nMacroSize );
1708 // set frame format from OBJ record, it is used if chart itself is transparent
1709 if( mxChart )
1710 mxChart->UpdateObjFrame( maLineData, maFillData );
1713 void XclImpChartObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1715 // read OBJ record and the following chart substream
1716 ReadFrameData( rStrm );
1717 rStrm.Ignore( 18 );
1718 ReadMacro4( rStrm, nMacroSize );
1719 // set frame format from OBJ record, it is used if chart itself is transparent
1720 if( mxChart )
1721 mxChart->UpdateObjFrame( maLineData, maFillData );
1724 void XclImpChartObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1726 // read OBJ record and the following chart substream
1727 ReadFrameData( rStrm );
1728 rStrm.Ignore( 18 );
1729 ReadName5( rStrm, nNameLen );
1730 ReadMacro5( rStrm, nMacroSize );
1731 ReadChartSubStream( rStrm );
1732 // set frame format from OBJ record, it is used if chart itself is transparent
1733 if( mxChart )
1734 mxChart->UpdateObjFrame( maLineData, maFillData );
1737 void XclImpChartObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 /*nSubRecSize*/ )
1739 // read the following chart substream
1740 if( nSubRecId == EXC_ID_OBJEND )
1742 // enable CONTINUE handling for the entire chart substream
1743 rStrm.ResetRecord( true );
1744 ReadChartSubStream( rStrm );
1745 /* disable CONTINUE handling again to be able to read
1746 following CONTINUE records as MSODRAWING records. */
1747 rStrm.ResetRecord( false );
1751 std::size_t XclImpChartObj::DoGetProgressSize() const
1753 return mxChart ? mxChart->GetProgressSize() : 1;
1756 SdrObjectUniquePtr XclImpChartObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
1758 SdrObjectUniquePtr xSdrObj;
1759 SfxObjectShell* pDocShell = GetDocShell();
1760 if( rDffConv.SupportsOleObjects() && SvtModuleOptions().IsChart() && pDocShell && mxChart && !mxChart->IsPivotChart() )
1762 // create embedded chart object
1763 OUString aEmbObjName;
1764 OUString sBaseURL(GetRoot().GetMedium().GetBaseURL());
1765 Reference< XEmbeddedObject > xEmbObj = pDocShell->GetEmbeddedObjectContainer().
1766 CreateEmbeddedObject( SvGlobalName( SO3_SCH_CLASSID ).GetByteSequence(), aEmbObjName, &sBaseURL );
1768 /* Set the size to the embedded object, this prevents that font sizes
1769 of text objects are changed in the chart when the object is
1770 inserted into the draw page. */
1771 sal_Int64 nAspect = css::embed::Aspects::MSOLE_CONTENT;
1772 MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xEmbObj->getMapUnit( nAspect ) );
1773 Size aSize( OutputDevice::LogicToLogic( rAnchorRect.GetSize(), MapMode( MapUnit::Map100thMM ), MapMode( aUnit ) ) );
1774 css::awt::Size aAwtSize( aSize.Width(), aSize.Height() );
1775 xEmbObj->setVisualAreaSize( nAspect, aAwtSize );
1777 // #i121334# This call will change the chart's default background fill from white to transparent.
1778 // Add here again if this is wanted (see task description for details)
1779 // ChartHelper::AdaptDefaultsForChart( xEmbObj );
1781 // create the container OLE object
1782 xSdrObj.reset(
1783 new SdrOle2Obj(
1784 *GetDoc().GetDrawLayer(),
1785 svt::EmbeddedObjectRef(xEmbObj, nAspect),
1786 aEmbObjName,
1787 rAnchorRect));
1790 return xSdrObj;
1793 void XclImpChartObj::DoPostProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const
1795 const SdrOle2Obj* pSdrOleObj = dynamic_cast< const SdrOle2Obj* >( &rSdrObj );
1796 if( !(mxChart && pSdrOleObj) )
1797 return;
1799 const Reference< XEmbeddedObject >& xEmbObj = pSdrOleObj->GetObjRef();
1800 if( xEmbObj.is() && ::svt::EmbeddedObjectRef::TryRunningState( xEmbObj ) ) try
1802 Reference< XEmbedPersist > xPersist( xEmbObj, UNO_QUERY_THROW );
1803 Reference< XModel > xModel( xEmbObj->getComponent(), UNO_QUERY_THROW );
1804 mxChart->Convert( xModel, rDffConv, xPersist->getEntryName(), rSdrObj.GetLogicRect() );
1806 catch( const Exception& )
1811 void XclImpChartObj::FinalizeTabChart()
1813 /* #i44077# Calculate and store DFF anchor for sheet charts.
1814 Needed to get used area if this chart is inserted as OLE object. */
1815 OSL_ENSURE( mbOwnTab, "XclImpChartObj::FinalizeTabChart - not allowed for embedded chart objects" );
1817 // set uninitialized page to landscape
1818 if( !GetPageSettings().GetPageData().mbValid )
1819 GetPageSettings().SetPaperSize( EXC_PAPERSIZE_DEFAULT, false );
1821 // calculate size of the chart object
1822 const XclPageData& rPageData = GetPageSettings().GetPageData();
1823 Size aPaperSize = rPageData.GetScPaperSize();
1825 tools::Long nWidth = XclTools::GetHmmFromTwips( aPaperSize.Width() );
1826 tools::Long nHeight = XclTools::GetHmmFromTwips( aPaperSize.Height() );
1828 // subtract page margins, give some more extra space
1829 nWidth -= o3tl::saturating_add(XclTools::GetHmmFromInch(rPageData.mfLeftMargin + rPageData.mfRightMargin), static_cast<sal_Int32>(2000));
1830 nHeight -= o3tl::saturating_add(XclTools::GetHmmFromInch(rPageData.mfTopMargin + rPageData.mfBottomMargin), static_cast<sal_Int32>(1000));
1832 // print column/row headers?
1833 if( rPageData.mbPrintHeadings )
1835 nWidth -= 2000;
1836 nHeight -= 1000;
1839 // create the object anchor
1840 XclObjAnchor aAnchor;
1841 aAnchor.SetRect( GetRoot(), GetCurrScTab(), tools::Rectangle( 1000, 500, nWidth, nHeight ), MapUnit::Map100thMM );
1842 SetAnchor( aAnchor );
1845 XclImpNoteObj::XclImpNoteObj( const XclImpRoot& rRoot ) :
1846 XclImpTextObj( rRoot ),
1847 maScPos( ScAddress::INITIALIZE_INVALID ),
1848 mnNoteFlags( 0 )
1850 SetSimpleMacro( false );
1851 // caption object will be created manually
1852 SetInsertSdrObj( false );
1855 void XclImpNoteObj::SetNoteData( const ScAddress& rScPos, sal_uInt16 nNoteFlags )
1857 maScPos = rScPos;
1858 mnNoteFlags = nNoteFlags;
1861 void XclImpNoteObj::DoPreProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const
1863 // create formatted text
1864 XclImpTextObj::DoPreProcessSdrObj( rDffConv, rSdrObj );
1865 OutlinerParaObject* pOutlinerObj = rSdrObj.GetOutlinerParaObject();
1866 if( maScPos.IsValid() && pOutlinerObj )
1868 // create cell note with all data from drawing object
1869 ScNoteUtil::CreateNoteFromObjectData(
1870 GetDoc(), maScPos,
1871 rSdrObj.GetMergedItemSet().CloneAsValue(), // new object on heap expected
1872 *pOutlinerObj,
1873 rSdrObj.GetLogicRect(),
1874 ::get_flag( mnNoteFlags, EXC_NOTE_VISIBLE ) );
1878 XclImpControlHelper::XclImpControlHelper( const XclImpRoot& rRoot, XclCtrlBindMode eBindMode ) :
1879 mrRoot( rRoot ),
1880 meBindMode( eBindMode )
1884 XclImpControlHelper::~XclImpControlHelper()
1888 SdrObjectUniquePtr XclImpControlHelper::CreateSdrObjectFromShape(
1889 const Reference< XShape >& rxShape, const tools::Rectangle& rAnchorRect ) const
1891 mxShape = rxShape;
1892 SdrObjectUniquePtr xSdrObj( SdrObject::getSdrObjectFromXShape( rxShape ) );
1893 if( xSdrObj )
1895 xSdrObj->NbcSetSnapRect( rAnchorRect );
1896 // #i30543# insert into control layer
1897 xSdrObj->NbcSetLayer( SC_LAYER_CONTROLS );
1899 return xSdrObj;
1902 void XclImpControlHelper::ApplySheetLinkProps() const
1905 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( mxShape );
1906 if( !xCtrlModel.is() )
1907 return;
1909 // sheet links
1910 SfxObjectShell* pDocShell = mrRoot.GetDocShell();
1911 if(!pDocShell)
1912 return;
1914 Reference< XMultiServiceFactory > xFactory( pDocShell->GetModel(), UNO_QUERY );
1915 if( !xFactory.is() )
1916 return;
1918 // cell link
1919 if( mxCellLink ) try
1921 Reference< XBindableValue > xBindable( xCtrlModel, UNO_QUERY_THROW );
1923 // create argument sequence for createInstanceWithArguments()
1924 CellAddress aApiAddress;
1925 ScUnoConversion::FillApiAddress( aApiAddress, *mxCellLink );
1927 NamedValue aValue;
1928 aValue.Name = SC_UNONAME_BOUNDCELL;
1929 aValue.Value <<= aApiAddress;
1931 Sequence< Any > aArgs{ Any(aValue) };
1933 // create the CellValueBinding instance and set at the control model
1934 OUString aServiceName;
1935 switch( meBindMode )
1937 case EXC_CTRL_BINDCONTENT: aServiceName = SC_SERVICENAME_VALBIND; break;
1938 case EXC_CTRL_BINDPOSITION: aServiceName = SC_SERVICENAME_LISTCELLBIND; break;
1940 Reference< XValueBinding > xBinding(
1941 xFactory->createInstanceWithArguments( aServiceName, aArgs ), UNO_QUERY_THROW );
1942 xBindable->setValueBinding( xBinding );
1944 catch( const Exception& )
1948 // source range
1949 if( !mxSrcRange )
1950 return;
1954 Reference< XListEntrySink > xEntrySink( xCtrlModel, UNO_QUERY_THROW );
1956 // create argument sequence for createInstanceWithArguments()
1957 CellRangeAddress aApiRange;
1958 ScUnoConversion::FillApiRange( aApiRange, *mxSrcRange );
1960 NamedValue aValue;
1961 aValue.Name = SC_UNONAME_CELLRANGE;
1962 aValue.Value <<= aApiRange;
1964 Sequence< Any > aArgs{ Any(aValue) };
1966 // create the EntrySource instance and set at the control model
1967 Reference< XListEntrySource > xEntrySource( xFactory->createInstanceWithArguments(
1968 SC_SERVICENAME_LISTSOURCE, aArgs ), UNO_QUERY_THROW );
1969 xEntrySink->setListEntrySource( xEntrySource );
1971 catch( const Exception& )
1976 void XclImpControlHelper::ProcessControl( const XclImpDrawObjBase& rDrawObj ) const
1978 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( mxShape );
1979 if( !xCtrlModel.is() )
1980 return;
1982 ApplySheetLinkProps();
1984 ScfPropertySet aPropSet( xCtrlModel );
1986 // #i51348# set object name at control model
1987 aPropSet.SetStringProperty( "Name", rDrawObj.GetObjName() );
1989 // control visible and printable?
1990 aPropSet.SetBoolProperty( "EnableVisible", rDrawObj.IsVisible() );
1991 aPropSet.SetBoolProperty( "Printable", rDrawObj.IsPrintable() );
1993 // virtual call for type specific processing
1994 DoProcessControl( aPropSet );
1997 void XclImpControlHelper::ReadCellLinkFormula( XclImpStream& rStrm, bool bWithBoundSize )
1999 ScRangeList aScRanges;
2000 ReadRangeList( aScRanges, rStrm, bWithBoundSize );
2001 // Use first cell of first range
2002 if ( !aScRanges.empty() )
2004 const ScRange & rScRange = aScRanges.front();
2005 mxCellLink = std::make_shared<ScAddress>( rScRange.aStart );
2009 void XclImpControlHelper::ReadSourceRangeFormula( XclImpStream& rStrm, bool bWithBoundSize )
2011 ScRangeList aScRanges;
2012 ReadRangeList( aScRanges, rStrm, bWithBoundSize );
2013 // Use first range
2014 if ( !aScRanges.empty() )
2016 const ScRange & rScRange = aScRanges.front();
2017 mxSrcRange = std::make_shared<ScRange>( rScRange );
2021 void XclImpControlHelper::DoProcessControl( ScfPropertySet& ) const
2025 void XclImpControlHelper::ReadRangeList( ScRangeList& rScRanges, XclImpStream& rStrm )
2027 XclTokenArray aXclTokArr;
2028 sal_uInt16 nSize = XclTokenArray::ReadSize(rStrm);
2029 rStrm.Ignore( 4 );
2030 aXclTokArr.ReadArray(nSize, rStrm);
2031 mrRoot.GetFormulaCompiler().CreateRangeList( rScRanges, EXC_FMLATYPE_CONTROL, aXclTokArr, rStrm );
2034 void XclImpControlHelper::ReadRangeList( ScRangeList& rScRanges, XclImpStream& rStrm, bool bWithBoundSize )
2036 if( bWithBoundSize )
2038 sal_uInt16 nSize;
2039 nSize = rStrm.ReaduInt16();
2040 if( nSize > 0 )
2042 rStrm.PushPosition();
2043 ReadRangeList( rScRanges, rStrm );
2044 rStrm.PopPosition();
2045 rStrm.Ignore( nSize );
2048 else
2050 ReadRangeList( rScRanges, rStrm );
2054 XclImpTbxObjBase::XclImpTbxObjBase( const XclImpRoot& rRoot ) :
2055 XclImpTextObj( rRoot ),
2056 XclImpControlHelper( rRoot, EXC_CTRL_BINDPOSITION )
2058 SetSimpleMacro( false );
2059 SetCustomDffObj( true );
2062 namespace {
2064 void lclExtractColor( sal_uInt8& rnColorIdx, const DffPropSet& rDffPropSet, sal_uInt32 nPropId )
2066 if( rDffPropSet.IsProperty( nPropId ) )
2068 sal_uInt32 nColor = rDffPropSet.GetPropertyValue( nPropId, 0 );
2069 if( (nColor & 0xFF000000) == 0x08000000 )
2070 rnColorIdx = ::extract_value< sal_uInt8 >( nColor, 0, 8 );
2074 } // namespace
2076 void XclImpTbxObjBase::SetDffProperties( const DffPropSet& rDffPropSet )
2078 maFillData.mnPattern = rDffPropSet.GetPropertyBool( DFF_Prop_fFilled ) ? EXC_PATT_SOLID : EXC_PATT_NONE;
2079 lclExtractColor( maFillData.mnBackColorIdx, rDffPropSet, DFF_Prop_fillBackColor );
2080 lclExtractColor( maFillData.mnPattColorIdx, rDffPropSet, DFF_Prop_fillColor );
2081 ::set_flag( maFillData.mnAuto, EXC_OBJ_LINE_AUTO, false );
2083 maLineData.mnStyle = rDffPropSet.GetPropertyBool( DFF_Prop_fLine ) ? EXC_OBJ_LINE_SOLID : EXC_OBJ_LINE_NONE;
2084 lclExtractColor( maLineData.mnColorIdx, rDffPropSet, DFF_Prop_lineColor );
2085 ::set_flag( maLineData.mnAuto, EXC_OBJ_FILL_AUTO, false );
2088 bool XclImpTbxObjBase::FillMacroDescriptor( ScriptEventDescriptor& rDescriptor ) const
2090 return XclControlHelper::FillMacroDescriptor( rDescriptor, DoGetEventType(), GetMacroName(), GetDocShell() );
2093 void XclImpTbxObjBase::ConvertFont( ScfPropertySet& rPropSet ) const
2095 if( maTextData.mxString )
2097 const XclFormatRunVec& rFormatRuns = maTextData.mxString->GetFormats();
2098 if( rFormatRuns.empty() )
2099 GetFontBuffer().WriteDefaultCtrlFontProperties( rPropSet );
2100 else
2101 GetFontBuffer().WriteFontProperties( rPropSet, EXC_FONTPROPSET_CONTROL, rFormatRuns.front().mnFontIdx );
2105 void XclImpTbxObjBase::ConvertLabel( ScfPropertySet& rPropSet ) const
2107 if( maTextData.mxString )
2109 OUString aLabel = maTextData.mxString->GetText();
2110 if( maTextData.maData.mnShortcut > 0 )
2112 sal_Int32 nPos = aLabel.indexOf( static_cast< sal_Unicode >( maTextData.maData.mnShortcut ) );
2113 if( nPos != -1 )
2114 aLabel = aLabel.replaceAt( nPos, 0, u"~" );
2116 rPropSet.SetStringProperty( "Label", aLabel );
2118 //Excel Alt text <==> Aoo description
2119 //For TBX control, if user does not operate alt text, alt text will be set label text as default value in Excel.
2120 //In this case, DFF_Prop_wzDescription will not be set in excel file.
2121 //So In the end of SvxMSDffManager::ImportShape, description will not be set. But actually in excel,
2122 //the alt text is the label value. So here set description as label text first which is called before ImportShape.
2123 Reference< css::beans::XPropertySet > xPropset( mxShape, UNO_QUERY );
2124 try{
2125 if(xPropset.is())
2126 xPropset->setPropertyValue( "Description", makeAny(aLabel) );
2127 }catch( ... )
2129 SAL_WARN("sc.filter", "Can't set a default text for TBX Control ");
2132 ConvertFont( rPropSet );
2135 SdrObjectUniquePtr XclImpTbxObjBase::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
2137 SdrObjectUniquePtr xSdrObj( rDffConv.CreateSdrObject( *this, rAnchorRect ) );
2138 rDffConv.Progress();
2139 return xSdrObj;
2142 void XclImpTbxObjBase::DoPreProcessSdrObj( XclImpDffConverter& /*rDffConv*/, SdrObject& /*rSdrObj*/ ) const
2144 // do not call DoPreProcessSdrObj() from base class (to skip text processing)
2145 ProcessControl( *this );
2148 XclImpButtonObj::XclImpButtonObj( const XclImpRoot& rRoot ) :
2149 XclImpTbxObjBase( rRoot )
2153 void XclImpButtonObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2155 // label and text formatting
2156 ConvertLabel( rPropSet );
2158 /* Horizontal text alignment. For unknown reason, the property type is a
2159 simple sal_Int16 and not a com.sun.star.style.HorizontalAlignment. */
2160 sal_Int16 nHorAlign = 1;
2161 switch( maTextData.maData.GetHorAlign() )
2163 case EXC_OBJ_HOR_LEFT: nHorAlign = 0; break;
2164 case EXC_OBJ_HOR_CENTER: nHorAlign = 1; break;
2165 case EXC_OBJ_HOR_RIGHT: nHorAlign = 2; break;
2167 rPropSet.SetProperty( "Align", nHorAlign );
2169 // vertical text alignment
2170 namespace csss = ::com::sun::star::style;
2171 csss::VerticalAlignment eVerAlign = csss::VerticalAlignment_MIDDLE;
2172 switch( maTextData.maData.GetVerAlign() )
2174 case EXC_OBJ_VER_TOP: eVerAlign = csss::VerticalAlignment_TOP; break;
2175 case EXC_OBJ_VER_CENTER: eVerAlign = csss::VerticalAlignment_MIDDLE; break;
2176 case EXC_OBJ_VER_BOTTOM: eVerAlign = csss::VerticalAlignment_BOTTOM; break;
2178 rPropSet.SetProperty( "VerticalAlign", eVerAlign );
2180 // always wrap text automatically
2181 rPropSet.SetBoolProperty( "MultiLine", true );
2183 // default button
2184 bool bDefButton = ::get_flag( maTextData.maData.mnButtonFlags, EXC_OBJ_BUTTON_DEFAULT );
2185 rPropSet.SetBoolProperty( "DefaultButton", bDefButton );
2187 // button type (flags cannot be combined in OOo)
2188 namespace cssa = ::com::sun::star::awt;
2189 cssa::PushButtonType eButtonType = cssa::PushButtonType_STANDARD;
2190 if( ::get_flag( maTextData.maData.mnButtonFlags, EXC_OBJ_BUTTON_CLOSE ) )
2191 eButtonType = cssa::PushButtonType_OK;
2192 else if( ::get_flag( maTextData.maData.mnButtonFlags, EXC_OBJ_BUTTON_CANCEL ) )
2193 eButtonType = cssa::PushButtonType_CANCEL;
2194 else if( ::get_flag( maTextData.maData.mnButtonFlags, EXC_OBJ_BUTTON_HELP ) )
2195 eButtonType = cssa::PushButtonType_HELP;
2196 // property type is short, not enum
2197 rPropSet.SetProperty( "PushButtonType", sal_Int16( eButtonType ) );
2200 OUString XclImpButtonObj::DoGetServiceName() const
2202 return "com.sun.star.form.component.CommandButton";
2205 XclTbxEventType XclImpButtonObj::DoGetEventType() const
2207 return EXC_TBX_EVENT_ACTION;
2210 XclImpCheckBoxObj::XclImpCheckBoxObj( const XclImpRoot& rRoot ) :
2211 XclImpTbxObjBase( rRoot ),
2212 mnState( EXC_OBJ_CHECKBOX_UNCHECKED ),
2213 mnCheckBoxFlags( 0 )
2217 void XclImpCheckBoxObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2219 ReadFrameData( rStrm );
2220 rStrm.Ignore( 10 );
2221 maTextData.maData.mnFlags = rStrm.ReaduInt16();
2222 rStrm.Ignore( 20 );
2223 ReadName5( rStrm, nNameLen );
2224 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2225 ReadCellLinkFormula( rStrm, true );
2226 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2227 maTextData.ReadByteString( rStrm );
2228 mnState = rStrm.ReaduInt16();
2229 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2230 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16();
2231 mnCheckBoxFlags = rStrm.ReaduInt16();
2234 void XclImpCheckBoxObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2236 switch( nSubRecId )
2238 case EXC_ID_OBJCBLS:
2239 // do not read EXC_ID_OBJCBLSDATA, not written by OOo Excel export
2240 mnState = rStrm.ReaduInt16();
2241 rStrm.Ignore( 4 );
2242 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2243 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16();
2244 mnCheckBoxFlags = rStrm.ReaduInt16();
2245 break;
2246 case EXC_ID_OBJCBLSFMLA:
2247 ReadCellLinkFormula( rStrm, false );
2248 break;
2249 default:
2250 XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2254 void XclImpCheckBoxObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2256 // label and text formatting
2257 ConvertLabel( rPropSet );
2259 // state
2260 bool bSupportsTristate = GetObjType() == EXC_OBJTYPE_CHECKBOX;
2261 sal_Int16 nApiState = 0;
2262 switch( mnState )
2264 case EXC_OBJ_CHECKBOX_UNCHECKED: nApiState = 0; break;
2265 case EXC_OBJ_CHECKBOX_CHECKED: nApiState = 1; break;
2266 case EXC_OBJ_CHECKBOX_TRISTATE: nApiState = bSupportsTristate ? 2 : 1; break;
2268 if( bSupportsTristate )
2269 rPropSet.SetBoolProperty( "TriState", nApiState == 2 );
2270 rPropSet.SetProperty( "DefaultState", nApiState );
2272 // box style
2273 namespace AwtVisualEffect = ::com::sun::star::awt::VisualEffect;
2274 sal_Int16 nEffect = ::get_flagvalue( mnCheckBoxFlags, EXC_OBJ_CHECKBOX_FLAT, AwtVisualEffect::FLAT, AwtVisualEffect::LOOK3D );
2275 rPropSet.SetProperty( "VisualEffect", nEffect );
2277 // do not wrap text automatically
2278 rPropSet.SetBoolProperty( "MultiLine", false );
2280 // #i40279# always centered vertically
2281 namespace csss = ::com::sun::star::style;
2282 rPropSet.SetProperty( "VerticalAlign", csss::VerticalAlignment_MIDDLE );
2284 // background color
2285 if( maFillData.IsFilled() )
2287 sal_Int32 nColor = static_cast< sal_Int32 >( GetSolidFillColor( maFillData ) );
2288 rPropSet.SetProperty( "BackgroundColor", nColor );
2292 OUString XclImpCheckBoxObj::DoGetServiceName() const
2294 return "com.sun.star.form.component.CheckBox";
2297 XclTbxEventType XclImpCheckBoxObj::DoGetEventType() const
2299 return EXC_TBX_EVENT_ACTION;
2302 XclImpOptionButtonObj::XclImpOptionButtonObj( const XclImpRoot& rRoot ) :
2303 XclImpCheckBoxObj( rRoot ),
2304 mnNextInGroup( 0 ),
2305 mnFirstInGroup( 1 )
2309 void XclImpOptionButtonObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2311 ReadFrameData( rStrm );
2312 rStrm.Ignore( 10 );
2313 maTextData.maData.mnFlags = rStrm.ReaduInt16();
2314 rStrm.Ignore( 32 );
2315 ReadName5( rStrm, nNameLen );
2316 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2317 ReadCellLinkFormula( rStrm, true );
2318 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2319 maTextData.ReadByteString( rStrm );
2320 mnState = rStrm.ReaduInt16();
2321 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2322 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16();
2323 mnCheckBoxFlags = rStrm.ReaduInt16();
2324 mnNextInGroup = rStrm.ReaduInt16();
2325 mnFirstInGroup = rStrm.ReaduInt16();
2328 void XclImpOptionButtonObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2330 switch( nSubRecId )
2332 case EXC_ID_OBJRBODATA:
2333 mnNextInGroup = rStrm.ReaduInt16();
2334 mnFirstInGroup = rStrm.ReaduInt16();
2335 break;
2336 default:
2337 XclImpCheckBoxObj::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2341 void XclImpOptionButtonObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2343 XclImpCheckBoxObj::DoProcessControl( rPropSet );
2344 // TODO: grouping
2345 XclImpOptionButtonObj* pTbxObj = dynamic_cast< XclImpOptionButtonObj* >( GetObjectManager().GetSheetDrawing( GetTab() ).FindDrawObj( mnNextInGroup ).get() );
2346 if ( pTbxObj && pTbxObj->mnFirstInGroup )
2348 // Group has terminated
2349 // traverse each RadioButton in group and
2350 // a) apply the groupname
2351 // b) propagate the linked cell from the lead radiobutton
2352 // c) apply the correct Ref value
2353 XclImpOptionButtonObj* pLeader = pTbxObj;
2355 sal_Int32 nRefVal = 1;
2359 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( pTbxObj->mxShape );
2360 if ( xCtrlModel.is() )
2362 ScfPropertySet aProps( xCtrlModel );
2363 OUString sGroupName = OUString::number( pLeader->GetDffShapeId() );
2365 aProps.SetStringProperty( "GroupName", sGroupName );
2366 aProps.SetStringProperty( "RefValue", OUString::number( nRefVal++ ) );
2367 if ( pLeader->HasCellLink() && !pTbxObj->HasCellLink() )
2369 // propagate cell link info
2370 pTbxObj->mxCellLink = std::make_shared<ScAddress>( *pLeader->mxCellLink );
2371 pTbxObj->ApplySheetLinkProps();
2373 pTbxObj = dynamic_cast< XclImpOptionButtonObj* >( GetObjectManager().GetSheetDrawing( GetTab() ).FindDrawObj( pTbxObj->mnNextInGroup ).get() );
2375 else
2376 pTbxObj = nullptr;
2377 } while ( pTbxObj && ( pTbxObj->mnFirstInGroup != 1 ) );
2379 else
2381 // not the leader? try and find it
2385 OUString XclImpOptionButtonObj::DoGetServiceName() const
2387 return "com.sun.star.form.component.RadioButton";
2390 XclTbxEventType XclImpOptionButtonObj::DoGetEventType() const
2392 return EXC_TBX_EVENT_ACTION;
2395 XclImpLabelObj::XclImpLabelObj( const XclImpRoot& rRoot ) :
2396 XclImpTbxObjBase( rRoot )
2400 void XclImpLabelObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2402 // label and text formatting
2403 ConvertLabel( rPropSet );
2405 // text alignment (always top/left aligned)
2406 rPropSet.SetProperty( "Align", sal_Int16( 0 ) );
2407 namespace csss = ::com::sun::star::style;
2408 rPropSet.SetProperty( "VerticalAlign", csss::VerticalAlignment_TOP );
2410 // always wrap text automatically
2411 rPropSet.SetBoolProperty( "MultiLine", true );
2414 OUString XclImpLabelObj::DoGetServiceName() const
2416 return "com.sun.star.form.component.FixedText";
2419 XclTbxEventType XclImpLabelObj::DoGetEventType() const
2421 return EXC_TBX_EVENT_MOUSE;
2424 XclImpGroupBoxObj::XclImpGroupBoxObj( const XclImpRoot& rRoot ) :
2425 XclImpTbxObjBase( rRoot ),
2426 mnGroupBoxFlags( 0 )
2430 void XclImpGroupBoxObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2432 ReadFrameData( rStrm );
2433 rStrm.Ignore( 10 );
2434 maTextData.maData.mnFlags = rStrm.ReaduInt16();
2435 rStrm.Ignore( 26 );
2436 ReadName5( rStrm, nNameLen );
2437 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2438 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2439 maTextData.ReadByteString( rStrm );
2440 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2441 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16( );
2442 mnGroupBoxFlags = rStrm.ReaduInt16();
2445 void XclImpGroupBoxObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2447 switch( nSubRecId )
2449 case EXC_ID_OBJGBODATA:
2450 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2451 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16();
2452 mnGroupBoxFlags = rStrm.ReaduInt16();
2453 break;
2454 default:
2455 XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2459 void XclImpGroupBoxObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2461 // label and text formatting
2462 ConvertLabel( rPropSet );
2465 OUString XclImpGroupBoxObj::DoGetServiceName() const
2467 return "com.sun.star.form.component.GroupBox";
2470 XclTbxEventType XclImpGroupBoxObj::DoGetEventType() const
2472 return EXC_TBX_EVENT_MOUSE;
2475 XclImpDialogObj::XclImpDialogObj( const XclImpRoot& rRoot ) :
2476 XclImpTbxObjBase( rRoot )
2480 void XclImpDialogObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2482 // label and text formatting
2483 ConvertLabel( rPropSet );
2486 OUString XclImpDialogObj::DoGetServiceName() const
2488 // dialog frame faked by a groupbox
2489 return "com.sun.star.form.component.GroupBox";
2492 XclTbxEventType XclImpDialogObj::DoGetEventType() const
2494 return EXC_TBX_EVENT_MOUSE;
2497 XclImpEditObj::XclImpEditObj( const XclImpRoot& rRoot ) :
2498 XclImpTbxObjBase( rRoot ),
2499 mnContentType( EXC_OBJ_EDIT_TEXT ),
2500 mnMultiLine( 0 ),
2501 mnScrollBar( 0 ),
2502 mnListBoxObjId( 0 )
2506 bool XclImpEditObj::IsNumeric() const
2508 return (mnContentType == EXC_OBJ_EDIT_INTEGER) || (mnContentType == EXC_OBJ_EDIT_DOUBLE);
2511 void XclImpEditObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2513 ReadFrameData( rStrm );
2514 rStrm.Ignore( 10 );
2515 maTextData.maData.mnFlags = rStrm.ReaduInt16();
2516 rStrm.Ignore( 14 );
2517 ReadName5( rStrm, nNameLen );
2518 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2519 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2520 maTextData.ReadByteString( rStrm );
2521 mnContentType = rStrm.ReaduInt16();
2522 mnMultiLine = rStrm.ReaduInt16();
2523 mnScrollBar = rStrm.ReaduInt16();
2524 mnListBoxObjId = rStrm.ReaduInt16();
2527 void XclImpEditObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2529 switch( nSubRecId )
2531 case EXC_ID_OBJEDODATA:
2532 mnContentType = rStrm.ReaduInt16();
2533 mnMultiLine = rStrm.ReaduInt16();
2534 mnScrollBar = rStrm.ReaduInt16();
2535 mnListBoxObjId = rStrm.ReaduInt16();
2536 break;
2537 default:
2538 XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2542 void XclImpEditObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2544 if( maTextData.mxString )
2546 OUString aText = maTextData.mxString->GetText();
2547 if( IsNumeric() )
2549 // TODO: OUString::toDouble() does not handle local decimal separator
2550 rPropSet.SetProperty( "DefaultValue", aText.toDouble() );
2551 rPropSet.SetBoolProperty( "Spin", mnScrollBar != 0 );
2553 else
2555 rPropSet.SetProperty( "DefaultText", aText );
2556 rPropSet.SetBoolProperty( "MultiLine", mnMultiLine != 0 );
2557 rPropSet.SetBoolProperty( "VScroll", mnScrollBar != 0 );
2560 ConvertFont( rPropSet );
2563 OUString XclImpEditObj::DoGetServiceName() const
2565 return IsNumeric() ?
2566 OUString( "com.sun.star.form.component.NumericField" ) :
2567 OUString( "com.sun.star.form.component.TextField" );
2570 XclTbxEventType XclImpEditObj::DoGetEventType() const
2572 return EXC_TBX_EVENT_TEXT;
2575 XclImpTbxObjScrollableBase::XclImpTbxObjScrollableBase( const XclImpRoot& rRoot ) :
2576 XclImpTbxObjBase( rRoot ),
2577 mnValue( 0 ),
2578 mnMin( 0 ),
2579 mnMax( 100 ),
2580 mnStep( 1 ),
2581 mnPageStep( 10 ),
2582 mnOrient( 0 ),
2583 mnThumbWidth( 1 ),
2584 mnScrollFlags( 0 )
2588 void XclImpTbxObjScrollableBase::ReadSbs( XclImpStream& rStrm )
2590 rStrm.Ignore( 4 );
2591 mnValue = rStrm.ReaduInt16();
2592 mnMin = rStrm.ReaduInt16();
2593 mnMax = rStrm.ReaduInt16();
2594 mnStep = rStrm.ReaduInt16();
2595 mnPageStep = rStrm.ReaduInt16();
2596 mnOrient = rStrm.ReaduInt16();
2597 mnThumbWidth = rStrm.ReaduInt16();
2598 mnScrollFlags = rStrm.ReaduInt16();
2601 void XclImpTbxObjScrollableBase::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2603 switch( nSubRecId )
2605 case EXC_ID_OBJSBS:
2606 ReadSbs( rStrm );
2607 break;
2608 case EXC_ID_OBJSBSFMLA:
2609 ReadCellLinkFormula( rStrm, false );
2610 break;
2611 default:
2612 XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2616 XclImpSpinButtonObj::XclImpSpinButtonObj( const XclImpRoot& rRoot ) :
2617 XclImpTbxObjScrollableBase( rRoot )
2621 void XclImpSpinButtonObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2623 ReadFrameData( rStrm );
2624 ReadSbs( rStrm );
2625 ReadName5( rStrm, nNameLen );
2626 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2627 ReadCellLinkFormula( rStrm, true );
2630 void XclImpSpinButtonObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2632 // Calc's "Border" property is not the 3D/flat style effect in Excel (#i34712#)
2633 rPropSet.SetProperty( "Border", css::awt::VisualEffect::NONE );
2634 rPropSet.SetProperty< sal_Int32 >( "DefaultSpinValue", mnValue );
2635 rPropSet.SetProperty< sal_Int32 >( "SpinValueMin", mnMin );
2636 rPropSet.SetProperty< sal_Int32 >( "SpinValueMax", mnMax );
2637 rPropSet.SetProperty< sal_Int32 >( "SpinIncrement", mnStep );
2639 // Excel spin buttons always vertical
2640 rPropSet.SetProperty( "Orientation", css::awt::ScrollBarOrientation::VERTICAL );
2643 OUString XclImpSpinButtonObj::DoGetServiceName() const
2645 return "com.sun.star.form.component.SpinButton";
2648 XclTbxEventType XclImpSpinButtonObj::DoGetEventType() const
2650 return EXC_TBX_EVENT_VALUE;
2653 XclImpScrollBarObj::XclImpScrollBarObj( const XclImpRoot& rRoot ) :
2654 XclImpTbxObjScrollableBase( rRoot )
2658 void XclImpScrollBarObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2660 ReadFrameData( rStrm );
2661 ReadSbs( rStrm );
2662 ReadName5( rStrm, nNameLen );
2663 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2664 ReadCellLinkFormula( rStrm, true );
2667 void XclImpScrollBarObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2669 // Calc's "Border" property is not the 3D/flat style effect in Excel (#i34712#)
2670 rPropSet.SetProperty( "Border", css::awt::VisualEffect::NONE );
2671 rPropSet.SetProperty< sal_Int32 >( "DefaultScrollValue", mnValue );
2672 rPropSet.SetProperty< sal_Int32 >( "ScrollValueMin", mnMin );
2673 rPropSet.SetProperty< sal_Int32 >( "ScrollValueMax", mnMax );
2674 rPropSet.SetProperty< sal_Int32 >( "LineIncrement", mnStep );
2675 rPropSet.SetProperty< sal_Int32 >( "BlockIncrement", mnPageStep );
2676 rPropSet.SetProperty( "VisibleSize", ::std::min< sal_Int32 >( mnPageStep, 1 ) );
2678 namespace AwtScrollOrient = ::com::sun::star::awt::ScrollBarOrientation;
2679 sal_Int32 nApiOrient = ::get_flagvalue( mnOrient, EXC_OBJ_SCROLLBAR_HOR, AwtScrollOrient::HORIZONTAL, AwtScrollOrient::VERTICAL );
2680 rPropSet.SetProperty( "Orientation", nApiOrient );
2683 OUString XclImpScrollBarObj::DoGetServiceName() const
2685 return "com.sun.star.form.component.ScrollBar";
2688 XclTbxEventType XclImpScrollBarObj::DoGetEventType() const
2690 return EXC_TBX_EVENT_VALUE;
2693 XclImpTbxObjListBase::XclImpTbxObjListBase( const XclImpRoot& rRoot ) :
2694 XclImpTbxObjScrollableBase( rRoot ),
2695 mnEntryCount( 0 ),
2696 mnSelEntry( 0 ),
2697 mnListFlags( 0 ),
2698 mnEditObjId( 0 ),
2699 mbHasDefFontIdx( false )
2703 void XclImpTbxObjListBase::ReadLbsData( XclImpStream& rStrm )
2705 ReadSourceRangeFormula( rStrm, true );
2706 mnEntryCount = rStrm.ReaduInt16();
2707 mnSelEntry = rStrm.ReaduInt16();
2708 mnListFlags = rStrm.ReaduInt16();
2709 mnEditObjId = rStrm.ReaduInt16();
2712 void XclImpTbxObjListBase::SetBoxFormatting( ScfPropertySet& rPropSet ) const
2714 // border style
2715 namespace AwtVisualEffect = ::com::sun::star::awt::VisualEffect;
2716 sal_Int16 nApiBorder = ::get_flagvalue( mnListFlags, EXC_OBJ_LISTBOX_FLAT, AwtVisualEffect::FLAT, AwtVisualEffect::LOOK3D );
2717 rPropSet.SetProperty( "Border", nApiBorder );
2719 // font formatting
2720 if( mbHasDefFontIdx )
2721 GetFontBuffer().WriteFontProperties( rPropSet, EXC_FONTPROPSET_CONTROL, maTextData.maData.mnDefFontIdx );
2722 else
2723 GetFontBuffer().WriteDefaultCtrlFontProperties( rPropSet );
2726 XclImpListBoxObj::XclImpListBoxObj( const XclImpRoot& rRoot ) :
2727 XclImpTbxObjListBase( rRoot )
2731 void XclImpListBoxObj::ReadFullLbsData( XclImpStream& rStrm, std::size_t nRecLeft )
2733 std::size_t nRecEnd = rStrm.GetRecPos() + nRecLeft;
2734 ReadLbsData( rStrm );
2735 OSL_ENSURE( (rStrm.GetRecPos() == nRecEnd) || (rStrm.GetRecPos() + mnEntryCount == nRecEnd),
2736 "XclImpListBoxObj::ReadFullLbsData - invalid size of OBJLBSDATA record" );
2737 while (rStrm.IsValid())
2739 if (rStrm.GetRecPos() >= nRecEnd)
2740 break;
2741 maSelection.push_back( rStrm.ReaduInt8() );
2745 void XclImpListBoxObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2747 ReadFrameData( rStrm );
2748 ReadSbs( rStrm );
2749 rStrm.Ignore( 18 );
2750 maTextData.maData.mnDefFontIdx = rStrm.ReaduInt16();
2751 rStrm.Ignore( 4 );
2752 ReadName5( rStrm, nNameLen );
2753 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2754 ReadCellLinkFormula( rStrm, true );
2755 ReadFullLbsData( rStrm, rStrm.GetRecLeft() );
2756 mbHasDefFontIdx = true;
2759 void XclImpListBoxObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2761 switch( nSubRecId )
2763 case EXC_ID_OBJLBSDATA:
2764 ReadFullLbsData( rStrm, nSubRecSize );
2765 break;
2766 default:
2767 XclImpTbxObjListBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2771 void XclImpListBoxObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2773 // listbox formatting
2774 SetBoxFormatting( rPropSet );
2776 // selection type
2777 sal_uInt8 nSelType = ::extract_value< sal_uInt8 >( mnListFlags, 4, 2 );
2778 bool bMultiSel = nSelType != EXC_OBJ_LISTBOX_SINGLE;
2779 rPropSet.SetBoolProperty( "MultiSelection", bMultiSel );
2781 // selection (do not set, if listbox is linked to a cell)
2782 if( HasCellLink() )
2783 return;
2785 ScfInt16Vec aSelVec;
2787 // multi selection: API expects sequence of list entry indexes
2788 if( bMultiSel )
2790 sal_Int16 nIndex = 0;
2791 for( const auto& rItem : maSelection )
2793 if( rItem != 0 )
2794 aSelVec.push_back( nIndex );
2795 ++nIndex;
2798 // single selection: mnSelEntry is one-based, API expects zero-based
2799 else if( mnSelEntry > 0 )
2800 aSelVec.push_back( static_cast< sal_Int16 >( mnSelEntry - 1 ) );
2802 if( !aSelVec.empty() )
2804 Sequence<sal_Int16> aSelSeq(aSelVec.data(), static_cast<sal_Int32>(aSelVec.size()));
2805 rPropSet.SetProperty( "DefaultSelection", aSelSeq );
2809 OUString XclImpListBoxObj::DoGetServiceName() const
2811 return "com.sun.star.form.component.ListBox";
2814 XclTbxEventType XclImpListBoxObj::DoGetEventType() const
2816 return EXC_TBX_EVENT_CHANGE;
2819 XclImpDropDownObj::XclImpDropDownObj( const XclImpRoot& rRoot ) :
2820 XclImpTbxObjListBase( rRoot ),
2821 mnLeft( 0 ),
2822 mnTop( 0 ),
2823 mnRight( 0 ),
2824 mnBottom( 0 ),
2825 mnDropDownFlags( 0 ),
2826 mnLineCount( 0 ),
2827 mnMinWidth( 0 )
2831 sal_uInt16 XclImpDropDownObj::GetDropDownType() const
2833 return ::extract_value< sal_uInt8 >( mnDropDownFlags, 0, 2 );
2836 void XclImpDropDownObj::ReadFullLbsData( XclImpStream& rStrm )
2838 ReadLbsData( rStrm );
2839 mnDropDownFlags = rStrm.ReaduInt16();
2840 mnLineCount = rStrm.ReaduInt16();
2841 mnMinWidth = rStrm.ReaduInt16();
2842 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2843 maTextData.ReadByteString( rStrm );
2844 // dropdowns of auto-filters have 'simple' style, they don't have a text area
2845 if( GetDropDownType() == EXC_OBJ_DROPDOWN_SIMPLE )
2846 SetProcessSdrObj( false );
2849 void XclImpDropDownObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2851 ReadFrameData( rStrm );
2852 ReadSbs( rStrm );
2853 rStrm.Ignore( 18 );
2854 maTextData.maData.mnDefFontIdx = rStrm.ReaduInt16();
2855 rStrm.Ignore( 14 );
2856 mnLeft = rStrm.ReaduInt16();
2857 mnTop = rStrm.ReaduInt16();
2858 mnRight = rStrm.ReaduInt16();
2859 mnBottom = rStrm.ReaduInt16();
2860 rStrm.Ignore( 4 );
2861 ReadName5( rStrm, nNameLen );
2862 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2863 ReadCellLinkFormula( rStrm, true );
2864 ReadFullLbsData( rStrm );
2865 mbHasDefFontIdx = true;
2868 void XclImpDropDownObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2870 switch( nSubRecId )
2872 case EXC_ID_OBJLBSDATA:
2873 ReadFullLbsData( rStrm );
2874 break;
2875 default:
2876 XclImpTbxObjListBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2880 void XclImpDropDownObj::DoProcessControl( ScfPropertySet& rPropSet ) const
2882 // dropdown listbox formatting
2883 SetBoxFormatting( rPropSet );
2884 // enable dropdown button
2885 rPropSet.SetBoolProperty( "Dropdown", true );
2886 // dropdown line count
2887 rPropSet.SetProperty( "LineCount", mnLineCount );
2889 if( GetDropDownType() == EXC_OBJ_DROPDOWN_COMBOBOX )
2891 // text of editable combobox
2892 if( maTextData.mxString )
2893 rPropSet.SetStringProperty( "DefaultText", maTextData.mxString->GetText() );
2895 else
2897 // selection (do not set, if dropdown is linked to a cell)
2898 if( !HasCellLink() && (mnSelEntry > 0) )
2900 Sequence< sal_Int16 > aSelSeq{ o3tl::narrowing<sal_Int16>(mnSelEntry - 1) };
2901 rPropSet.SetProperty( "DefaultSelection", aSelSeq );
2906 OUString XclImpDropDownObj::DoGetServiceName() const
2908 return (GetDropDownType() == EXC_OBJ_DROPDOWN_COMBOBOX) ?
2909 OUString( "com.sun.star.form.component.ComboBox" ) :
2910 OUString( "com.sun.star.form.component.ListBox" );
2913 XclTbxEventType XclImpDropDownObj::DoGetEventType() const
2915 return (GetDropDownType() == EXC_OBJ_DROPDOWN_COMBOBOX) ? EXC_TBX_EVENT_TEXT : EXC_TBX_EVENT_CHANGE;
2918 XclImpPictureObj::XclImpPictureObj( const XclImpRoot& rRoot ) :
2919 XclImpRectObj( rRoot ),
2920 XclImpControlHelper( rRoot, EXC_CTRL_BINDCONTENT ),
2921 mnStorageId( 0 ),
2922 mnCtlsStrmPos( 0 ),
2923 mnCtlsStrmSize( 0 ),
2924 mbEmbedded( false ),
2925 mbLinked( false ),
2926 mbSymbol( false ),
2927 mbControl( false ),
2928 mbUseCtlsStrm( false )
2930 SetAreaObj( true );
2931 SetSimpleMacro( true );
2932 SetCustomDffObj( true );
2935 OUString XclImpPictureObj::GetOleStorageName() const
2937 OUStringBuffer aStrgName;
2938 if( (mbEmbedded || mbLinked) && !mbControl && (mnStorageId > 0) )
2940 aStrgName = mbEmbedded ? std::u16string_view(u"" EXC_STORAGE_OLE_EMBEDDED) : std::u16string_view(u"" EXC_STORAGE_OLE_LINKED);
2941 static const char spcHexChars[] = "0123456789ABCDEF";
2942 for( sal_uInt8 nIndex = 32; nIndex > 0; nIndex -= 4 )
2943 aStrgName.append(OUStringChar( spcHexChars[ ::extract_value< sal_uInt8 >( mnStorageId, nIndex - 4, 4 ) ] ));
2945 return aStrgName.makeStringAndClear();
2948 void XclImpPictureObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
2950 sal_uInt16 nLinkSize;
2951 ReadFrameData( rStrm );
2952 rStrm.Ignore( 6 );
2953 nLinkSize = rStrm.ReaduInt16();
2954 rStrm.Ignore( 2 );
2955 ReadFlags3( rStrm );
2956 ReadMacro3( rStrm, nMacroSize );
2957 ReadPictFmla( rStrm, nLinkSize );
2959 if( (rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord() )
2960 maGraphic = XclImpDrawing::ReadImgData( GetRoot(), rStrm );
2963 void XclImpPictureObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
2965 sal_uInt16 nLinkSize;
2966 ReadFrameData( rStrm );
2967 rStrm.Ignore( 6 );
2968 nLinkSize = rStrm.ReaduInt16();
2969 rStrm.Ignore( 2 );
2970 ReadFlags3( rStrm );
2971 ReadMacro4( rStrm, nMacroSize );
2972 ReadPictFmla( rStrm, nLinkSize );
2974 if( (rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord() )
2975 maGraphic = XclImpDrawing::ReadImgData( GetRoot(), rStrm );
2978 void XclImpPictureObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
2980 sal_uInt16 nLinkSize;
2981 ReadFrameData( rStrm );
2982 rStrm.Ignore( 6 );
2983 nLinkSize = rStrm.ReaduInt16();
2984 rStrm.Ignore( 2 );
2985 ReadFlags3( rStrm );
2986 rStrm.Ignore( 4 );
2987 ReadName5( rStrm, nNameLen );
2988 ReadMacro5( rStrm, nMacroSize );
2989 ReadPictFmla( rStrm, nLinkSize );
2991 if( (rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord() )
2993 // page background is stored as hidden picture with name "__BkgndObj"
2994 if ( IsHidden() && (GetObjName() == "__BkgndObj") )
2995 GetPageSettings().ReadImgData( rStrm );
2996 else
2997 maGraphic = XclImpDrawing::ReadImgData( GetRoot(), rStrm );
3001 void XclImpPictureObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
3003 switch( nSubRecId )
3005 case EXC_ID_OBJFLAGS:
3006 ReadFlags8( rStrm );
3007 break;
3008 case EXC_ID_OBJPICTFMLA:
3009 ReadPictFmla( rStrm, rStrm.ReaduInt16() );
3010 break;
3011 default:
3012 XclImpDrawObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
3016 SdrObjectUniquePtr XclImpPictureObj::DoCreateSdrObj( XclImpDffConverter& rDffConv, const tools::Rectangle& rAnchorRect ) const
3018 // try to create an OLE object or form control
3019 SdrObjectUniquePtr xSdrObj( rDffConv.CreateSdrObject( *this, rAnchorRect ) );
3021 // insert a graphic replacement for unsupported ole object ( if none already
3022 // exists ) Hmm ok, it's possibly that there has been some imported
3023 // graphic at a base level but unlikely, normally controls have a valid
3024 // preview in the IMGDATA record ( see below )
3025 // It might be possible to push such an imported graphic up to this
3026 // XclImpPictureObj instance but there are so many layers of indirection I
3027 // don't see an easy way. This way at least ensures that we can
3028 // avoid a 'blank' shape that can result from a failed control import
3029 if ( !xSdrObj && IsOcxControl() && maGraphic.GetType() == GraphicType::NONE )
3031 const_cast< XclImpPictureObj* >( this )->maGraphic =
3032 SdrOle2Obj::GetEmptyOLEReplacementGraphic();
3034 // no OLE - create a plain picture from IMGDATA record data
3035 if( !xSdrObj && (maGraphic.GetType() != GraphicType::NONE) )
3037 xSdrObj.reset(
3038 new SdrGrafObj(
3039 *GetDoc().GetDrawLayer(),
3040 maGraphic,
3041 rAnchorRect));
3042 ConvertRectStyle( *xSdrObj );
3045 rDffConv.Progress();
3046 return xSdrObj;
3049 OUString XclImpPictureObj::GetObjName() const
3051 if( IsOcxControl() )
3053 OUString sName( GetObjectManager().GetOleNameOverride( GetTab(), GetObjId() ) );
3054 if (!sName.isEmpty())
3055 return sName;
3057 return XclImpDrawObjBase::GetObjName();
3060 void XclImpPictureObj::DoPreProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const
3062 if( IsOcxControl() )
3064 // do not call XclImpRectObj::DoPreProcessSdrObj(), it would trace missing "printable" feature
3065 ProcessControl( *this );
3067 else if( mbEmbedded || mbLinked )
3069 // trace missing "printable" feature
3070 XclImpRectObj::DoPreProcessSdrObj( rDffConv, rSdrObj );
3072 SfxObjectShell* pDocShell = GetDocShell();
3073 SdrOle2Obj* pOleSdrObj = dynamic_cast< SdrOle2Obj* >( &rSdrObj );
3074 if( pOleSdrObj && pDocShell )
3076 comphelper::EmbeddedObjectContainer& rEmbObjCont = pDocShell->GetEmbeddedObjectContainer();
3077 Reference< XEmbeddedObject > xEmbObj = pOleSdrObj->GetObjRef();
3078 OUString aOldName( pOleSdrObj->GetPersistName() );
3080 /* The object persistence should be already in the storage, but
3081 the object still might not be inserted into the container. */
3082 if( rEmbObjCont.HasEmbeddedObject( aOldName ) )
3084 if( !rEmbObjCont.HasEmbeddedObject( xEmbObj ) )
3085 // filter code is allowed to call the following method
3086 rEmbObjCont.AddEmbeddedObject( xEmbObj, aOldName );
3088 else
3090 /* If the object is still not in container it must be inserted
3091 there, the name must be generated in this case. */
3092 OUString aNewName;
3093 rEmbObjCont.InsertEmbeddedObject( xEmbObj, aNewName );
3094 if( aOldName != aNewName )
3095 // SetPersistName, not SetName
3096 pOleSdrObj->SetPersistName( aNewName );
3102 void XclImpPictureObj::ReadFlags3( XclImpStream& rStrm )
3104 sal_uInt16 nFlags;
3105 nFlags = rStrm.ReaduInt16();
3106 mbSymbol = ::get_flag( nFlags, EXC_OBJ_PIC_SYMBOL );
3109 void XclImpPictureObj::ReadFlags8( XclImpStream& rStrm )
3111 sal_uInt16 nFlags;
3112 nFlags = rStrm.ReaduInt16();
3113 mbSymbol = ::get_flag( nFlags, EXC_OBJ_PIC_SYMBOL );
3114 mbControl = ::get_flag( nFlags, EXC_OBJ_PIC_CONTROL );
3115 mbUseCtlsStrm = ::get_flag( nFlags, EXC_OBJ_PIC_CTLSSTREAM );
3116 OSL_ENSURE( mbControl || !mbUseCtlsStrm, "XclImpPictureObj::ReadFlags8 - CTLS stream for controls only" );
3117 SetProcessSdrObj( mbControl || !mbUseCtlsStrm );
3120 void XclImpPictureObj::ReadPictFmla( XclImpStream& rStrm, sal_uInt16 nLinkSize )
3122 std::size_t nLinkEnd = rStrm.GetRecPos() + nLinkSize;
3123 if( nLinkSize >= 6 )
3125 sal_uInt16 nFmlaSize;
3126 nFmlaSize = rStrm.ReaduInt16();
3127 OSL_ENSURE( nFmlaSize > 0, "XclImpPictureObj::ReadPictFmla - missing link formula" );
3128 // BIFF3/BIFF4 do not support storages, nothing to do here
3129 if( (nFmlaSize > 0) && (GetBiff() >= EXC_BIFF5) )
3131 rStrm.Ignore( 4 );
3132 sal_uInt8 nToken;
3133 nToken = rStrm.ReaduInt8();
3135 // different processing for linked vs. embedded OLE objects
3136 if( nToken == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ) )
3138 mbLinked = true;
3139 switch( GetBiff() )
3141 case EXC_BIFF5:
3143 sal_Int16 nRefIdx;
3144 sal_uInt16 nNameIdx;
3145 nRefIdx = rStrm.ReadInt16();
3146 rStrm.Ignore( 8 );
3147 nNameIdx = rStrm.ReaduInt16();
3148 rStrm.Ignore( 12 );
3149 const ExtName* pExtName = GetOldRoot().pExtNameBuff->GetNameByIndex( nRefIdx, nNameIdx );
3150 if( pExtName && pExtName->IsOLE() )
3151 mnStorageId = pExtName->nStorageId;
3153 break;
3154 case EXC_BIFF8:
3156 sal_uInt16 nXti, nExtName;
3157 nXti = rStrm.ReaduInt16();
3158 nExtName = rStrm.ReaduInt16();
3159 const XclImpExtName* pExtName = GetLinkManager().GetExternName( nXti, nExtName );
3160 if( pExtName && (pExtName->GetType() == xlExtOLE) )
3161 mnStorageId = pExtName->GetStorageId();
3163 break;
3164 default:
3165 DBG_ERROR_BIFF();
3168 else if( nToken == XclTokenArrayHelper::GetTokenId( EXC_TOKID_TBL, EXC_TOKCLASS_NONE ) )
3170 mbEmbedded = true;
3171 OSL_ENSURE( nFmlaSize == 5, "XclImpPictureObj::ReadPictFmla - unexpected formula size" );
3172 rStrm.Ignore( nFmlaSize - 1 ); // token ID already read
3173 if( nFmlaSize & 1 )
3174 rStrm.Ignore( 1 ); // padding byte
3176 // a class name may follow inside the picture link
3177 if( rStrm.GetRecPos() + 2 <= nLinkEnd )
3179 sal_uInt16 nLen = rStrm.ReaduInt16();
3180 if( nLen > 0 )
3181 maClassName = (GetBiff() == EXC_BIFF8) ? rStrm.ReadUniString( nLen ) : rStrm.ReadRawByteString( nLen );
3184 // else: ignore other formulas, e.g. pictures linked to cell ranges
3188 // seek behind picture link data
3189 rStrm.Seek( nLinkEnd );
3191 // read additional data for embedded OLE objects following the picture link
3192 if( IsOcxControl() )
3194 // #i26521# form controls to be ignored
3195 if( maClassName == "Forms.HTML:Hidden.1" )
3197 SetProcessSdrObj( false );
3198 return;
3201 if( rStrm.GetRecLeft() <= 8 ) return;
3203 // position and size of control data in 'Ctls' stream
3204 mnCtlsStrmPos = static_cast< std::size_t >( rStrm.ReaduInt32() );
3205 mnCtlsStrmSize = static_cast< std::size_t >( rStrm.ReaduInt32() );
3207 if( rStrm.GetRecLeft() <= 8 ) return;
3209 // additional string (16-bit characters), e.g. for progress bar control
3210 sal_uInt32 nAddStrSize;
3211 nAddStrSize = rStrm.ReaduInt32();
3212 OSL_ENSURE( rStrm.GetRecLeft() >= nAddStrSize + 4, "XclImpPictureObj::ReadPictFmla - missing data" );
3213 if( rStrm.GetRecLeft() >= nAddStrSize + 4 )
3215 rStrm.Ignore( nAddStrSize );
3216 // cell link and source range
3217 ReadCellLinkFormula( rStrm, true );
3218 ReadSourceRangeFormula( rStrm, true );
3221 else if( mbEmbedded && (rStrm.GetRecLeft() >= 4) )
3223 mnStorageId = rStrm.ReaduInt32();
3227 // DFF stream conversion ======================================================
3229 void XclImpSolverContainer::InsertSdrObjectInfo( SdrObject& rSdrObj, sal_uInt32 nDffShapeId, ShapeFlag nDffFlags )
3231 if( nDffShapeId > 0 )
3233 maSdrInfoMap[ nDffShapeId ].Set( &rSdrObj, nDffFlags );
3234 maSdrObjMap[ &rSdrObj ] = nDffShapeId;
3238 void XclImpSolverContainer::RemoveSdrObjectInfo( SdrObject& rSdrObj )
3240 // remove info of passed object from the maps
3241 XclImpSdrObjMap::iterator aIt = maSdrObjMap.find( &rSdrObj );
3242 if( aIt != maSdrObjMap.end() )
3244 maSdrInfoMap.erase( aIt->second );
3245 maSdrObjMap.erase( aIt );
3248 // remove info of all child objects of a group object
3249 if( SdrObjGroup* pGroupObj = dynamic_cast< SdrObjGroup* >( &rSdrObj ) )
3251 if( SdrObjList* pSubList = pGroupObj->GetSubList() )
3253 // iterate flat over the list because this function already works recursively
3254 SdrObjListIter aObjIt( pSubList, SdrIterMode::Flat );
3255 for( SdrObject* pChildObj = aObjIt.Next(); pChildObj; pChildObj = aObjIt.Next() )
3256 RemoveSdrObjectInfo( *pChildObj );
3261 void XclImpSolverContainer::UpdateConnectorRules()
3263 for (auto const & pRule : aCList)
3265 UpdateConnection( pRule->nShapeA, pRule->pAObj, &pRule->nSpFlagsA );
3266 UpdateConnection( pRule->nShapeB, pRule->pBObj, &pRule->nSpFlagsB );
3267 UpdateConnection( pRule->nShapeC, pRule->pCObj );
3271 void XclImpSolverContainer::RemoveConnectorRules()
3273 aCList.clear();
3274 maSdrInfoMap.clear();
3275 maSdrObjMap.clear();
3278 void XclImpSolverContainer::UpdateConnection( sal_uInt32 nDffShapeId, SdrObject*& rpSdrObj, ShapeFlag* pnDffFlags )
3280 XclImpSdrInfoMap::const_iterator aIt = maSdrInfoMap.find( nDffShapeId );
3281 if( aIt != maSdrInfoMap.end() )
3283 rpSdrObj = aIt->second.mpSdrObj;
3284 if( pnDffFlags )
3285 *pnDffFlags = aIt->second.mnDffFlags;
3289 XclImpSimpleDffConverter::XclImpSimpleDffConverter( const XclImpRoot& rRoot, SvStream& rDffStrm ) :
3290 SvxMSDffManager( rDffStrm, rRoot.GetBasePath(), 0, nullptr, rRoot.GetDoc().GetDrawLayer(), 1440, COL_DEFAULT, nullptr ),
3291 XclImpRoot( rRoot )
3293 SetSvxMSDffSettings( SVXMSDFF_SETTINGS_CROP_BITMAPS | SVXMSDFF_SETTINGS_IMPORT_EXCEL );
3296 XclImpSimpleDffConverter::~XclImpSimpleDffConverter()
3300 bool XclImpSimpleDffConverter::GetColorFromPalette( sal_uInt16 nIndex, Color& rColor ) const
3302 Color nColor = GetPalette().GetColor( nIndex );
3304 if( nColor == COL_AUTO )
3305 return false;
3307 rColor = nColor;
3308 return true;
3311 XclImpDffConverter::XclImpDffConvData::XclImpDffConvData(
3312 XclImpDrawing& rDrawing, SdrModel& rSdrModel, SdrPage& rSdrPage ) :
3313 mrDrawing( rDrawing ),
3314 mrSdrModel( rSdrModel ),
3315 mrSdrPage( rSdrPage ),
3316 mnLastCtrlIndex( -1 ),
3317 mbHasCtrlForm( false )
3321 constexpr OUStringLiteral gaStdFormName( u"Standard" ); /// Standard name of control forms.
3323 XclImpDffConverter::XclImpDffConverter( const XclImpRoot& rRoot, SvStream& rDffStrm ) :
3324 XclImpSimpleDffConverter( rRoot, rDffStrm ),
3325 oox::ole::MSConvertOCXControls( rRoot.GetDocShell()->GetModel() ),
3326 mnOleImpFlags( 0 ),
3327 mbNotifyMacroEventRead(false)
3329 const SvtFilterOptions& rFilterOpt = SvtFilterOptions::Get();
3330 if( rFilterOpt.IsMathType2Math() )
3331 mnOleImpFlags |= OLE_MATHTYPE_2_STARMATH;
3332 if( rFilterOpt.IsWinWord2Writer() )
3333 mnOleImpFlags |= OLE_WINWORD_2_STARWRITER;
3334 if( rFilterOpt.IsPowerPoint2Impress() )
3335 mnOleImpFlags |= OLE_POWERPOINT_2_STARIMPRESS;
3337 // try to open the 'Ctls' storage stream containing OCX control properties
3338 mxCtlsStrm = OpenStream( EXC_STREAM_CTLS );
3340 // default text margin (convert EMU to drawing layer units)
3341 mnDefTextMargin = EXC_OBJ_TEXT_MARGIN;
3342 ScaleEmu( mnDefTextMargin );
3345 XclImpDffConverter::~XclImpDffConverter()
3349 OUString XclImpObjectManager::GetOleNameOverride( SCTAB nTab, sal_uInt16 nObjId )
3351 OUString sOleName;
3352 OUString sCodeName = GetExtDocOptions().GetCodeName( nTab );
3354 if (mxOleCtrlNameOverride.is() && mxOleCtrlNameOverride->hasByName(sCodeName))
3356 Reference< XIndexContainer > xIdToOleName;
3357 mxOleCtrlNameOverride->getByName( sCodeName ) >>= xIdToOleName;
3358 xIdToOleName->getByIndex( nObjId ) >>= sOleName;
3361 return sOleName;
3364 void XclImpDffConverter::StartProgressBar( std::size_t nProgressSize )
3366 mxProgress = std::make_shared<ScfProgressBar>( GetDocShell(), STR_PROGRESS_CALCULATING );
3367 mxProgress->AddSegment( nProgressSize );
3368 mxProgress->Activate();
3371 void XclImpDffConverter::Progress( std::size_t nDelta )
3373 OSL_ENSURE( mxProgress, "XclImpDffConverter::Progress - invalid call, no progress bar" );
3374 mxProgress->Progress( nDelta );
3377 void XclImpDffConverter::InitializeDrawing( XclImpDrawing& rDrawing, SdrModel& rSdrModel, SdrPage& rSdrPage )
3379 XclImpDffConvDataRef xConvData = std::make_shared<XclImpDffConvData>( rDrawing, rSdrModel, rSdrPage );
3380 maDataStack.push_back( xConvData );
3381 SetModel( &xConvData->mrSdrModel, 1440 );
3384 void XclImpDffConverter::ProcessObject( SdrObjList& rObjList, XclImpDrawObjBase& rDrawObj )
3386 if( !rDrawObj.IsProcessSdrObj() )
3387 return;
3389 const XclObjAnchor* pAnchor = rDrawObj.GetAnchor();
3390 if(!pAnchor)
3391 return;
3393 tools::Rectangle aAnchorRect = GetConvData().mrDrawing.CalcAnchorRect( *pAnchor, false );
3394 if( rDrawObj.IsValidSize( aAnchorRect ) )
3396 // CreateSdrObject() recursively creates embedded child objects
3397 SdrObjectUniquePtr xSdrObj( rDrawObj.CreateSdrObject( *this, aAnchorRect, false ) );
3398 if( xSdrObj )
3399 rDrawObj.PreProcessSdrObject( *this, *xSdrObj );
3400 // call InsertSdrObject() also, if SdrObject is missing
3401 InsertSdrObject( rObjList, rDrawObj, xSdrObj.release() );
3405 void XclImpDffConverter::ProcessDrawing( const XclImpDrawObjVector& rDrawObjs )
3407 SdrPage& rSdrPage = GetConvData().mrSdrPage;
3408 for( const auto& rxDrawObj : rDrawObjs )
3409 ProcessObject( rSdrPage, *rxDrawObj );
3412 void XclImpDffConverter::ProcessDrawing( SvStream& rDffStrm )
3414 if( rDffStrm.TellEnd() > 0 )
3416 rDffStrm.Seek( STREAM_SEEK_TO_BEGIN );
3417 DffRecordHeader aHeader;
3418 ReadDffRecordHeader( rDffStrm, aHeader );
3419 OSL_ENSURE( aHeader.nRecType == DFF_msofbtDgContainer, "XclImpDffConverter::ProcessDrawing - unexpected record" );
3420 if( aHeader.nRecType == DFF_msofbtDgContainer )
3421 ProcessDgContainer( rDffStrm, aHeader );
3425 void XclImpDffConverter::FinalizeDrawing()
3427 OSL_ENSURE( !maDataStack.empty(), "XclImpDffConverter::FinalizeDrawing - no drawing manager on stack" );
3428 maDataStack.pop_back();
3429 // restore previous model at core DFF converter
3430 if( !maDataStack.empty() )
3431 SetModel( &maDataStack.back()->mrSdrModel, 1440 );
3434 void XclImpDffConverter::NotifyMacroEventRead()
3436 if (mbNotifyMacroEventRead)
3437 return;
3438 comphelper::DocumentInfo::notifyMacroEventRead(mxModel);
3439 mbNotifyMacroEventRead = true;
3442 SdrObjectUniquePtr XclImpDffConverter::CreateSdrObject( const XclImpTbxObjBase& rTbxObj, const tools::Rectangle& rAnchorRect )
3444 SdrObjectUniquePtr xSdrObj;
3446 OUString aServiceName = rTbxObj.GetServiceName();
3447 if( SupportsOleObjects() && !aServiceName.isEmpty() ) try
3449 // create the form control from scratch
3450 Reference< XFormComponent > xFormComp( ScfApiHelper::CreateInstance( GetDocShell(), aServiceName ), UNO_QUERY_THROW );
3451 // set controls form, needed in virtual function InsertControl()
3452 InitControlForm();
3453 // try to insert the control into the form
3454 css::awt::Size aDummySize;
3455 Reference< XShape > xShape;
3456 XclImpDffConvData& rConvData = GetConvData();
3457 if( rConvData.mxCtrlForm.is() && InsertControl( xFormComp, aDummySize, &xShape, true ) )
3459 xSdrObj = rTbxObj.CreateSdrObjectFromShape( xShape, rAnchorRect );
3460 // try to attach a macro to the control
3461 ScriptEventDescriptor aDescriptor;
3462 if( (rConvData.mnLastCtrlIndex >= 0) && rTbxObj.FillMacroDescriptor( aDescriptor ) )
3464 NotifyMacroEventRead();
3465 Reference< XEventAttacherManager > xEventMgr( rConvData.mxCtrlForm, UNO_QUERY_THROW );
3466 xEventMgr->registerScriptEvent( rConvData.mnLastCtrlIndex, aDescriptor );
3470 catch( const Exception& )
3474 return xSdrObj;
3477 SdrObjectUniquePtr XclImpDffConverter::CreateSdrObject( const XclImpPictureObj& rPicObj, const tools::Rectangle& rAnchorRect )
3479 SdrObjectUniquePtr xSdrObj;
3481 if( SupportsOleObjects() )
3483 if( rPicObj.IsOcxControl() )
3485 if( mxCtlsStrm.is() ) try
3487 /* set controls form, needed in virtual function InsertControl()
3488 called from ReadOCXExcelKludgeStream() */
3489 InitControlForm();
3491 // read from mxCtlsStrm into xShape, insert the control model into the form
3492 Reference< XShape > xShape;
3493 if( GetConvData().mxCtrlForm.is() )
3495 Reference< XFormComponent > xFComp;
3496 ReadOCXCtlsStream( mxCtlsStrm, xFComp, rPicObj.GetCtlsStreamPos(), rPicObj.GetCtlsStreamSize() );
3497 // recreate the method formerly known as ReadOCXExcelKludgeStream()
3498 if ( xFComp.is() )
3500 css::awt::Size aSz; // not used in import
3501 ScfPropertySet aPropSet( xFComp );
3502 aPropSet.SetStringProperty( "Name", rPicObj.GetObjName() );
3503 InsertControl( xFComp, aSz,&xShape,true);
3504 xSdrObj = rPicObj.CreateSdrObjectFromShape( xShape, rAnchorRect );
3508 catch( const Exception& )
3512 else
3514 SfxObjectShell* pDocShell = GetDocShell();
3515 tools::SvRef<SotStorage> xSrcStrg = GetRootStorage();
3516 OUString aStrgName = rPicObj.GetOleStorageName();
3517 if( pDocShell && xSrcStrg.is() && (!aStrgName.isEmpty()) )
3519 // first try to resolve graphic from DFF storage
3520 Graphic aGraphic;
3521 tools::Rectangle aVisArea;
3522 if( !GetBLIP( GetPropertyValue( DFF_Prop_pib, 0 ), aGraphic, &aVisArea ) )
3524 // if not found, use graphic from object (imported from IMGDATA record)
3525 aGraphic = rPicObj.GetGraphic();
3527 if( aGraphic.GetType() != GraphicType::NONE )
3529 ErrCode nError = ERRCODE_NONE;
3530 namespace cssea = ::com::sun::star::embed::Aspects;
3531 sal_Int64 nAspects = rPicObj.IsSymbol() ? cssea::MSOLE_ICON : cssea::MSOLE_CONTENT;
3532 xSdrObj.reset(
3533 CreateSdrOLEFromStorage(
3534 GetConvData().mrSdrModel,
3535 aStrgName,
3536 xSrcStrg,
3537 pDocShell->GetStorage(),
3538 aGraphic,
3539 rAnchorRect,
3540 aVisArea,
3541 nullptr,
3542 nError,
3543 mnOleImpFlags,
3544 nAspects,
3545 GetRoot().GetMedium().GetBaseURL()));
3551 return xSdrObj;
3554 bool XclImpDffConverter::SupportsOleObjects() const
3556 return GetConvData().mrDrawing.SupportsOleObjects();
3559 // virtual functions ----------------------------------------------------------
3561 void XclImpDffConverter::ProcessClientAnchor2( SvStream& rDffStrm,
3562 DffRecordHeader& rHeader, DffObjData& rObjData )
3564 // find the OBJ record data related to the processed shape
3565 XclImpDffConvData& rConvData = GetConvData();
3566 XclImpDrawObjBase* pDrawObj = rConvData.mrDrawing.FindDrawObj( rObjData.rSpHd ).get();
3567 if(!pDrawObj)
3568 return;
3570 OSL_ENSURE( rHeader.nRecType == DFF_msofbtClientAnchor, "XclImpDffConverter::ProcessClientAnchor2 - no client anchor record" );
3571 XclObjAnchor aAnchor;
3572 rHeader.SeekToContent( rDffStrm );
3573 sal_uInt8 nFlags(0);
3574 rDffStrm.ReadUChar( nFlags );
3575 rDffStrm.SeekRel( 1 ); // flags
3576 rDffStrm >> aAnchor; // anchor format equal to BIFF5 OBJ records
3578 if (!rDffStrm.good())
3580 SAL_WARN("sc.filter", "ProcessClientAnchor2 short read");
3581 return;
3584 pDrawObj->SetAnchor( aAnchor );
3585 rObjData.aChildAnchor = rConvData.mrDrawing.CalcAnchorRect( aAnchor, true );
3586 rObjData.bChildAnchor = true;
3587 // page anchoring is the best approximation we have if mbMove
3588 // is set
3589 rObjData.bPageAnchor = ( nFlags & 0x1 );
3592 namespace {
3594 struct XclImpDrawObjClientData : public SvxMSDffClientData
3596 const XclImpDrawObjBase* m_pTopLevelObj;
3598 XclImpDrawObjClientData()
3599 : m_pTopLevelObj(nullptr)
3602 virtual void NotifyFreeObj(SdrObject*) override {}
3607 SdrObject* XclImpDffConverter::ProcessObj( SvStream& rDffStrm, DffObjData& rDffObjData,
3608 SvxMSDffClientData& rClientData, tools::Rectangle& /*rTextRect*/, SdrObject* pOldSdrObj )
3610 XclImpDffConvData& rConvData = GetConvData();
3612 /* pOldSdrObj passes a generated SdrObject. This function owns this object
3613 and can modify it. The function has either to return it back to caller
3614 or to delete it by itself. */
3615 SdrObjectUniquePtr xSdrObj( pOldSdrObj );
3617 // find the OBJ record data related to the processed shape
3618 XclImpDrawObjRef xDrawObj = rConvData.mrDrawing.FindDrawObj( rDffObjData.rSpHd );
3619 const tools::Rectangle& rAnchorRect = rDffObjData.aChildAnchor;
3621 // Do not process the global page group shape
3622 bool bGlobalPageGroup( rDffObjData.nSpFlags & ShapeFlag::Patriarch );
3623 if( !xDrawObj || !xDrawObj->IsProcessSdrObj() || bGlobalPageGroup )
3624 return nullptr; // simply return, xSdrObj will be destroyed
3626 /* Pass pointer to top-level object back to caller. If the processed
3627 object is embedded in a group, the pointer is already set to the
3628 top-level parent object. */
3629 XclImpDrawObjClientData& rDrawObjClientData = static_cast<XclImpDrawObjClientData&>(rClientData);
3630 const bool bIsTopLevel = !rDrawObjClientData.m_pTopLevelObj;
3631 if (bIsTopLevel )
3632 rDrawObjClientData.m_pTopLevelObj = xDrawObj.get();
3634 // connectors don't have to be area objects
3635 if( dynamic_cast< SdrEdgeObj* >( xSdrObj.get() ) )
3636 xDrawObj->SetAreaObj( false );
3638 /* Check for valid size for all objects. Needed to ignore lots of invisible
3639 phantom objects from deleted rows or columns (for performance reasons).
3640 #i30816# Include objects embedded in groups.
3641 #i58780# Ignore group shapes, size is not initialized. */
3642 bool bEmbeddedGroup = !bIsTopLevel && dynamic_cast< SdrObjGroup* >( xSdrObj.get() );
3643 if( !bEmbeddedGroup && !xDrawObj->IsValidSize( rAnchorRect ) )
3644 return nullptr; // simply return, xSdrObj will be destroyed
3646 // set shape information from DFF stream
3647 OUString aObjName = GetPropertyString( DFF_Prop_wzName, rDffStrm );
3648 OUString aHyperlink = ReadHlinkProperty( rDffStrm );
3649 bool bVisible = !GetPropertyBool( DFF_Prop_fHidden );
3650 bool bAutoMargin = GetPropertyBool( DFF_Prop_AutoTextMargin );
3651 xDrawObj->SetDffData( rDffObjData, aObjName, aHyperlink, bVisible, bAutoMargin );
3653 /* Connect textbox data (string, alignment, text orientation) to object.
3654 don't ask for a text-ID, DFF export doesn't set one. */
3655 if( XclImpTextObj* pTextObj = dynamic_cast< XclImpTextObj* >( xDrawObj.get() ) )
3656 if( const XclImpObjTextData* pTextData = rConvData.mrDrawing.FindTextData( rDffObjData.rSpHd ) )
3657 pTextObj->SetTextData( *pTextData );
3659 // copy line and fill formatting of TBX form controls from DFF properties
3660 if( XclImpTbxObjBase* pTbxObj = dynamic_cast< XclImpTbxObjBase* >( xDrawObj.get() ) )
3661 pTbxObj->SetDffProperties( *this );
3663 // try to create a custom SdrObject that overwrites the passed object
3664 SdrObjectUniquePtr xNewSdrObj( xDrawObj->CreateSdrObject( *this, rAnchorRect, true ) );
3665 if( xNewSdrObj )
3666 xSdrObj = std::move( xNewSdrObj );
3668 // process the SdrObject
3669 if( xSdrObj )
3671 // filled without color -> set system window color
3672 if( GetPropertyBool( DFF_Prop_fFilled ) && !IsProperty( DFF_Prop_fillColor ) )
3673 xSdrObj->SetMergedItem( XFillColorItem( OUString(), GetPalette().GetColor( EXC_COLOR_WINDOWBACK ) ) );
3675 // additional processing on the SdrObject
3676 xDrawObj->PreProcessSdrObject( *this, *xSdrObj );
3678 /* If the SdrObject will not be inserted into the draw page, delete it
3679 here. Happens e.g. for notes: The PreProcessSdrObject() call above
3680 has inserted the note into the document, and the SdrObject is not
3681 needed anymore. */
3682 if( !xDrawObj->IsInsertSdrObj() )
3683 xSdrObj.reset();
3686 if( xSdrObj )
3688 /* Store the relation between shape ID and SdrObject for connectors.
3689 Must be done here (and not in InsertSdrObject() function),
3690 otherwise all SdrObjects embedded in groups would be lost. */
3691 rConvData.maSolverCont.InsertSdrObjectInfo( *xSdrObj, xDrawObj->GetDffShapeId(), xDrawObj->GetDffFlags() );
3693 /* If the drawing object is embedded in a group object, call
3694 PostProcessSdrObject() here. For top-level objects this will be
3695 done automatically in InsertSdrObject() but grouped shapes are
3696 inserted into their groups somewhere in the SvxMSDffManager base
3697 class without chance of notification. Unfortunately, now this is
3698 called before the object is really inserted into its group object,
3699 but that should not have any effect for grouped objects. */
3700 if( !bIsTopLevel )
3701 xDrawObj->PostProcessSdrObject( *this, *xSdrObj );
3704 return xSdrObj.release();
3707 SdrObject* XclImpDffConverter::FinalizeObj(DffObjData& rDffObjData, SdrObject* pOldSdrObj )
3709 XclImpDffConvData& rConvData = GetConvData();
3711 /* pOldSdrObj passes a generated SdrObject. This function owns this object
3712 and can modify it. The function has either to return it back to caller
3713 or to delete it by itself. */
3714 SdrObjectUniquePtr xSdrObj( pOldSdrObj );
3716 // find the OBJ record data related to the processed shape
3717 XclImpDrawObjRef xDrawObj = rConvData.mrDrawing.FindDrawObj( rDffObjData.rSpHd );
3719 if( xSdrObj && xDrawObj )
3721 // cell anchoring
3722 if ( !rDffObjData.bPageAnchor )
3723 ScDrawLayer::SetCellAnchoredFromPosition( *xSdrObj, GetDoc(), xDrawObj->GetTab(), false );
3726 return xSdrObj.release();
3729 bool XclImpDffConverter::InsertControl( const Reference< XFormComponent >& rxFormComp,
3730 const css::awt::Size& /*rSize*/, Reference< XShape >* pxShape,
3731 bool /*bFloatingCtrl*/ )
3733 if( GetDocShell() ) try
3735 XclImpDffConvData& rConvData = GetConvData();
3736 Reference< XIndexContainer > xFormIC( rConvData.mxCtrlForm, UNO_QUERY_THROW );
3737 Reference< XControlModel > xCtrlModel( rxFormComp, UNO_QUERY_THROW );
3739 // create the control shape
3740 Reference< XShape > xShape( ScfApiHelper::CreateInstance( GetDocShell(), "com.sun.star.drawing.ControlShape" ), UNO_QUERY_THROW );
3741 Reference< XControlShape > xCtrlShape( xShape, UNO_QUERY_THROW );
3743 // insert the new control into the form
3744 sal_Int32 nNewIndex = xFormIC->getCount();
3745 xFormIC->insertByIndex( nNewIndex, Any( rxFormComp ) );
3746 // on success: store new index of the control for later use (macro events)
3747 rConvData.mnLastCtrlIndex = nNewIndex;
3749 // set control model at control shape and pass back shape to caller
3750 xCtrlShape->setControl( xCtrlModel );
3751 if( pxShape ) *pxShape = xShape;
3752 return true;
3754 catch( const Exception& )
3756 OSL_FAIL( "XclImpDffConverter::InsertControl - cannot create form control" );
3759 return false;
3762 // private --------------------------------------------------------------------
3764 XclImpDffConverter::XclImpDffConvData& XclImpDffConverter::GetConvData()
3766 OSL_ENSURE( !maDataStack.empty(), "XclImpDffConverter::GetConvData - no drawing manager on stack" );
3767 return *maDataStack.back();
3770 const XclImpDffConverter::XclImpDffConvData& XclImpDffConverter::GetConvData() const
3772 OSL_ENSURE( !maDataStack.empty(), "XclImpDffConverter::GetConvData - no drawing manager on stack" );
3773 return *maDataStack.back();
3776 OUString XclImpDffConverter::ReadHlinkProperty( SvStream& rDffStrm ) const
3778 /* Reads hyperlink data from a complex DFF property. Contents of this
3779 property are equal to the HLINK record, import of this record is
3780 implemented in class XclImpHyperlink. This function has to create an
3781 instance of the XclImpStream class to be able to reuse the
3782 functionality of XclImpHyperlink. */
3783 OUString aString;
3784 sal_uInt32 nBufferSize = GetPropertyValue( DFF_Prop_pihlShape, 0 );
3785 if( (0 < nBufferSize) && (nBufferSize <= 0xFFFF) && SeekToContent( DFF_Prop_pihlShape, rDffStrm ) )
3787 // create a faked BIFF record that can be read by XclImpStream class
3788 SvMemoryStream aMemStream;
3789 aMemStream.WriteUInt16( 0 ).WriteUInt16( nBufferSize );
3791 // copy from DFF stream to memory stream
3792 ::std::vector< sal_uInt8 > aBuffer( nBufferSize );
3793 sal_uInt8* pnData = aBuffer.data();
3794 if (rDffStrm.ReadBytes(pnData, nBufferSize) == nBufferSize)
3796 aMemStream.WriteBytes(pnData, nBufferSize);
3798 // create BIFF import stream to be able to use XclImpHyperlink class
3799 XclImpStream aXclStrm( aMemStream, GetRoot() );
3800 if( aXclStrm.StartNextRecord() )
3801 aString = XclImpHyperlink::ReadEmbeddedData( aXclStrm );
3804 return aString;
3807 bool XclImpDffConverter::ProcessDgContainer( SvStream& rDffStrm, const DffRecordHeader& rDgHeader )
3809 std::size_t nEndPos = rDgHeader.GetRecEndFilePos();
3810 bool isBreak(false);
3811 while (!isBreak && rDffStrm.good() && rDffStrm.Tell() < nEndPos)
3813 DffRecordHeader aHeader;
3814 ReadDffRecordHeader( rDffStrm, aHeader );
3815 switch( aHeader.nRecType )
3817 case DFF_msofbtSolverContainer:
3818 isBreak = !ProcessSolverContainer( rDffStrm, aHeader );
3819 break;
3820 case DFF_msofbtSpgrContainer:
3821 isBreak = !ProcessShGrContainer( rDffStrm, aHeader );
3822 break;
3823 default:
3824 isBreak = !aHeader.SeekToEndOfRecord( rDffStrm );
3827 // seek to end of drawing page container
3828 isBreak = !rDgHeader.SeekToEndOfRecord( rDffStrm );
3830 // #i12638# #i37900# connector rules
3831 XclImpSolverContainer& rSolverCont = GetConvData().maSolverCont;
3832 rSolverCont.UpdateConnectorRules();
3833 SolveSolver( rSolverCont );
3834 rSolverCont.RemoveConnectorRules();
3835 return !isBreak;
3838 bool XclImpDffConverter::ProcessShGrContainer( SvStream& rDffStrm, const DffRecordHeader& rShGrHeader )
3840 std::size_t nEndPos = rShGrHeader.GetRecEndFilePos();
3841 bool isBreak(false);
3842 while (!isBreak && rDffStrm.good() && rDffStrm.Tell() < nEndPos)
3844 DffRecordHeader aHeader;
3845 ReadDffRecordHeader( rDffStrm, aHeader );
3846 switch( aHeader.nRecType )
3848 case DFF_msofbtSpgrContainer:
3849 case DFF_msofbtSpContainer:
3850 isBreak = !ProcessShContainer( rDffStrm, aHeader );
3851 break;
3852 default:
3853 isBreak = !aHeader.SeekToEndOfRecord( rDffStrm );
3856 // seek to end of shape group container
3857 return rShGrHeader.SeekToEndOfRecord( rDffStrm ) && !isBreak;
3860 bool XclImpDffConverter::ProcessSolverContainer( SvStream& rDffStrm, const DffRecordHeader& rSolverHeader )
3862 // solver container wants to read the solver container header again
3863 rSolverHeader.SeekToBegOfRecord( rDffStrm );
3864 // read the entire solver container
3865 ReadSvxMSDffSolverContainer( rDffStrm, GetConvData().maSolverCont );
3866 // seek to end of solver container
3867 return rSolverHeader.SeekToEndOfRecord( rDffStrm );
3870 bool XclImpDffConverter::ProcessShContainer( SvStream& rDffStrm, const DffRecordHeader& rShHeader )
3872 rShHeader.SeekToBegOfRecord( rDffStrm );
3873 tools::Rectangle aDummy;
3874 XclImpDrawObjClientData aDrawObjClientData;
3875 /* The call to ImportObj() creates and returns a new SdrObject for the
3876 processed shape. We take ownership of the returned object here. If the
3877 shape is a group object, all embedded objects are created recursively,
3878 and the returned group object contains them all. ImportObj() calls the
3879 virtual functions ProcessClientAnchor2() and ProcessObj() and writes
3880 the pointer to the related draw object data (OBJ record) into aDrawObjClientData. */
3881 SdrObjectUniquePtr xSdrObj( ImportObj( rDffStrm, aDrawObjClientData, aDummy, aDummy, /*nCalledByGroup*/0, /*pShapeId*/nullptr ) );
3882 if (aDrawObjClientData.m_pTopLevelObj && xSdrObj )
3883 InsertSdrObject( GetConvData().mrSdrPage, *aDrawObjClientData.m_pTopLevelObj, xSdrObj.release() );
3884 return rShHeader.SeekToEndOfRecord( rDffStrm );
3887 void XclImpDffConverter::InsertSdrObject( SdrObjList& rObjList, const XclImpDrawObjBase& rDrawObj, SdrObject* pSdrObj )
3889 XclImpDffConvData& rConvData = GetConvData();
3890 /* Take ownership of the passed object. If insertion fails (e.g. rDrawObj
3891 states to skip insertion), the object is automatically deleted. */
3892 SdrObjectUniquePtr xSdrObj( pSdrObj );
3893 if( xSdrObj && rDrawObj.IsInsertSdrObj() )
3895 rObjList.NbcInsertObject( xSdrObj.release() );
3896 // callback to drawing manager for e.g. tracking of used sheet area
3897 rConvData.mrDrawing.OnObjectInserted( rDrawObj );
3898 // callback to drawing object for post processing (use pSdrObj, xSdrObj already released)
3899 rDrawObj.PostProcessSdrObject( *this, *pSdrObj );
3901 /* SdrObject still here? Insertion failed, remove data from shape ID map.
3902 The SdrObject will be destructed then. */
3903 if( xSdrObj )
3904 rConvData.maSolverCont.RemoveSdrObjectInfo( *xSdrObj );
3907 void XclImpDffConverter::InitControlForm()
3909 XclImpDffConvData& rConvData = GetConvData();
3910 if( rConvData.mbHasCtrlForm )
3911 return;
3913 rConvData.mbHasCtrlForm = true;
3914 if( !SupportsOleObjects() )
3915 return;
3919 Reference< XFormsSupplier > xFormsSupplier( rConvData.mrSdrPage.getUnoPage(), UNO_QUERY_THROW );
3920 Reference< XNameContainer > xFormsNC( xFormsSupplier->getForms(), UNO_SET_THROW );
3921 // find or create the Standard form used to insert the imported controls
3922 if( xFormsNC->hasByName( gaStdFormName ) )
3924 xFormsNC->getByName( gaStdFormName ) >>= rConvData.mxCtrlForm;
3926 else if( SfxObjectShell* pDocShell = GetDocShell() )
3928 rConvData.mxCtrlForm.set( ScfApiHelper::CreateInstance( pDocShell, "com.sun.star.form.component.Form" ), UNO_QUERY_THROW );
3929 xFormsNC->insertByName( gaStdFormName, Any( rConvData.mxCtrlForm ) );
3932 catch( const Exception& )
3937 // Drawing manager ============================================================
3939 XclImpDrawing::XclImpDrawing( const XclImpRoot& rRoot, bool bOleObjects ) :
3940 XclImpRoot( rRoot ),
3941 mbOleObjs( bOleObjects )
3945 XclImpDrawing::~XclImpDrawing()
3949 Graphic XclImpDrawing::ReadImgData( const XclImpRoot& rRoot, XclImpStream& rStrm )
3951 Graphic aGraphic;
3952 sal_uInt16 nFormat = rStrm.ReaduInt16();
3953 rStrm.Ignore( 2 );//nEnv
3954 sal_uInt32 nDataSize = rStrm.ReaduInt32();
3955 if( nDataSize <= rStrm.GetRecLeft() )
3957 switch( nFormat )
3959 case EXC_IMGDATA_WMF: ReadWmf( aGraphic, rStrm ); break;
3960 case EXC_IMGDATA_BMP: ReadBmp( aGraphic, rRoot, rStrm ); break;
3961 default: OSL_FAIL( "XclImpDrawing::ReadImgData - unknown image format" );
3964 return aGraphic;
3967 void XclImpDrawing::ReadObj( XclImpStream& rStrm )
3969 XclImpDrawObjRef xDrawObj;
3971 /* #i61786# In BIFF8 streams, OBJ records may occur without MSODRAWING
3972 records. In this case, the OBJ records are in BIFF5 format. Do a sanity
3973 check here that there is no DFF data loaded before. */
3974 OSL_ENSURE( maDffStrm.Tell() == 0, "XclImpDrawing::ReadObj - unexpected DFF stream data, OBJ will be ignored" );
3975 if( maDffStrm.Tell() == 0 ) switch( GetBiff() )
3977 case EXC_BIFF3:
3978 xDrawObj = XclImpDrawObjBase::ReadObj3( GetRoot(), rStrm );
3979 break;
3980 case EXC_BIFF4:
3981 xDrawObj = XclImpDrawObjBase::ReadObj4( GetRoot(), rStrm );
3982 break;
3983 case EXC_BIFF5:
3984 case EXC_BIFF8:
3985 xDrawObj = XclImpDrawObjBase::ReadObj5( GetRoot(), rStrm );
3986 break;
3987 default:
3988 DBG_ERROR_BIFF();
3991 if( xDrawObj )
3993 // insert into maRawObjs or into the last open group object
3994 maRawObjs.InsertGrouped( xDrawObj );
3995 // to be able to find objects by ID
3996 maObjMapId[ xDrawObj->GetObjId() ] = xDrawObj;
4000 void XclImpDrawing::ReadMsoDrawing( XclImpStream& rStrm )
4002 OSL_ENSURE_BIFF( GetBiff() == EXC_BIFF8 );
4003 // disable internal CONTINUE handling
4004 rStrm.ResetRecord( false );
4005 // read leading MSODRAWING record
4006 ReadDffRecord( rStrm );
4008 // read following drawing records, but do not start following unrelated record
4009 bool bLoop = true;
4010 while( bLoop ) switch( rStrm.GetNextRecId() )
4012 case EXC_ID_MSODRAWING:
4013 case EXC_ID_MSODRAWINGSEL:
4014 case EXC_ID_CONT:
4015 rStrm.StartNextRecord();
4016 ReadDffRecord( rStrm );
4017 break;
4018 case EXC_ID_OBJ:
4019 rStrm.StartNextRecord();
4020 ReadObj8( rStrm );
4021 break;
4022 case EXC_ID_TXO:
4023 rStrm.StartNextRecord();
4024 ReadTxo( rStrm );
4025 break;
4026 default:
4027 bLoop = false;
4030 // re-enable internal CONTINUE handling
4031 rStrm.ResetRecord( true );
4034 XclImpDrawObjRef XclImpDrawing::FindDrawObj( const DffRecordHeader& rHeader ) const
4036 /* maObjMap stores objects by position of the client data (OBJ record) in
4037 the DFF stream, which is always behind shape start position of the
4038 passed header. The function upper_bound() finds the first element in
4039 the map whose key is greater than the start position of the header. Its
4040 end position is used to test whether the found object is really related
4041 to the shape. */
4042 XclImpDrawObjRef xDrawObj;
4043 XclImpObjMap::const_iterator aIt = maObjMap.upper_bound( rHeader.GetRecBegFilePos() );
4044 if( (aIt != maObjMap.end()) && (aIt->first <= rHeader.GetRecEndFilePos()) )
4045 xDrawObj = aIt->second;
4046 return xDrawObj;
4049 XclImpDrawObjRef XclImpDrawing::FindDrawObj( sal_uInt16 nObjId ) const
4051 XclImpDrawObjRef xDrawObj;
4052 XclImpObjMapById::const_iterator aIt = maObjMapId.find( nObjId );
4053 if( aIt != maObjMapId.end() )
4054 xDrawObj = aIt->second;
4055 return xDrawObj;
4058 const XclImpObjTextData* XclImpDrawing::FindTextData( const DffRecordHeader& rHeader ) const
4060 /* maTextMap stores textbox data by position of the client data (TXO
4061 record) in the DFF stream, which is always behind shape start position
4062 of the passed header. The function upper_bound() finds the first
4063 element in the map whose key is greater than the start position of the
4064 header. Its end position is used to test whether the found object is
4065 really related to the shape. */
4066 XclImpObjTextMap::const_iterator aIt = maTextMap.upper_bound( rHeader.GetRecBegFilePos() );
4067 if( (aIt != maTextMap.end()) && (aIt->first <= rHeader.GetRecEndFilePos()) )
4068 return aIt->second.get();
4069 return nullptr;
4072 void XclImpDrawing::SetSkipObj( sal_uInt16 nObjId )
4074 maSkipObjs.push_back( nObjId );
4077 std::size_t XclImpDrawing::GetProgressSize() const
4079 return std::accumulate(maObjMap.begin(), maObjMap.end(), maRawObjs.GetProgressSize(),
4080 [](const std::size_t& rSum, const XclImpObjMap::value_type& rEntry) { return rSum + rEntry.second->GetProgressSize(); });
4083 void XclImpDrawing::ImplConvertObjects( XclImpDffConverter& rDffConv, SdrModel& rSdrModel, SdrPage& rSdrPage )
4085 //rhbz#636521, disable undo during conversion. faster, smaller and stops
4086 //temp objects being inserted into the undo list
4087 bool bOrigUndoStatus = rSdrModel.IsUndoEnabled();
4088 rSdrModel.EnableUndo(false);
4089 // register this drawing manager at the passed (global) DFF manager
4090 rDffConv.InitializeDrawing( *this, rSdrModel, rSdrPage );
4091 // process list of objects to be skipped
4092 for( const auto& rSkipObj : maSkipObjs )
4093 if( XclImpDrawObjBase* pDrawObj = FindDrawObj( rSkipObj ).get() )
4094 pDrawObj->SetProcessSdrObj( false );
4095 // process drawing objects without DFF data
4096 rDffConv.ProcessDrawing( maRawObjs );
4097 // process all objects in the DFF stream
4098 rDffConv.ProcessDrawing( maDffStrm );
4099 // unregister this drawing manager at the passed (global) DFF manager
4100 rDffConv.FinalizeDrawing();
4101 rSdrModel.EnableUndo(bOrigUndoStatus);
4104 // protected ------------------------------------------------------------------
4106 void XclImpDrawing::AppendRawObject( const XclImpDrawObjRef& rxDrawObj )
4108 OSL_ENSURE( rxDrawObj, "XclImpDrawing::AppendRawObject - unexpected empty reference" );
4109 maRawObjs.push_back( rxDrawObj );
4112 // private --------------------------------------------------------------------
4114 void XclImpDrawing::ReadWmf( Graphic& rGraphic, XclImpStream& rStrm ) // static helper
4116 // extract graphic data from IMGDATA and following CONTINUE records
4117 rStrm.Ignore( 8 );
4118 SvMemoryStream aMemStrm;
4119 rStrm.CopyToStream( aMemStrm, rStrm.GetRecLeft() );
4120 aMemStrm.Seek( STREAM_SEEK_TO_BEGIN );
4121 // import the graphic from memory stream
4122 GDIMetaFile aGDIMetaFile;
4123 if( ::ReadWindowMetafile( aMemStrm, aGDIMetaFile ) )
4124 rGraphic = aGDIMetaFile;
4127 void XclImpDrawing::ReadBmp( Graphic& rGraphic, const XclImpRoot& rRoot, XclImpStream& rStrm ) // static helper
4129 // extract graphic data from IMGDATA and following CONTINUE records
4130 SvMemoryStream aMemStrm;
4132 /* Excel 3 and 4 seem to write broken BMP data. Usually they write a
4133 DIBCOREHEADER (12 bytes) containing width, height, planes = 1, and
4134 pixel depth = 32 bit. After that, 3 unused bytes are added before the
4135 actual pixel data. This does even confuse Excel 5 and later, which
4136 cannot read the image data correctly. */
4137 if( rRoot.GetBiff() <= EXC_BIFF4 )
4139 rStrm.PushPosition();
4140 sal_uInt32 nHdrSize;
4141 sal_uInt16 nWidth, nHeight, nPlanes, nDepth;
4142 nHdrSize = rStrm.ReaduInt32();
4143 nWidth = rStrm.ReaduInt16();
4144 nHeight = rStrm.ReaduInt16();
4145 nPlanes = rStrm.ReaduInt16();
4146 nDepth = rStrm.ReaduInt16();
4147 if( (nHdrSize == 12) && (nPlanes == 1) && (nDepth == 32) )
4149 rStrm.Ignore( 3 );
4150 aMemStrm.SetEndian( SvStreamEndian::LITTLE );
4151 aMemStrm.WriteUInt32( nHdrSize ).WriteUInt16( nWidth ).WriteUInt16( nHeight ).WriteUInt16( nPlanes ).WriteUInt16( nDepth );
4152 rStrm.CopyToStream( aMemStrm, rStrm.GetRecLeft() );
4154 rStrm.PopPosition();
4157 // no special handling above -> just copy the remaining record data
4158 if( aMemStrm.Tell() == 0 )
4159 rStrm.CopyToStream( aMemStrm, rStrm.GetRecLeft() );
4161 // import the graphic from memory stream
4162 aMemStrm.Seek( STREAM_SEEK_TO_BEGIN );
4163 Bitmap aBitmap;
4164 if( ReadDIB(aBitmap, aMemStrm, false) ) // read DIB without file header
4165 rGraphic = BitmapEx(aBitmap);
4168 void XclImpDrawing::ReadDffRecord( XclImpStream& rStrm )
4170 maDffStrm.Seek( STREAM_SEEK_TO_END );
4171 rStrm.CopyRecordToStream( maDffStrm );
4174 void XclImpDrawing::ReadObj8( XclImpStream& rStrm )
4176 XclImpDrawObjRef xDrawObj = XclImpDrawObjBase::ReadObj8( GetRoot(), rStrm );
4177 // store the new object in the internal containers
4178 maObjMap[ maDffStrm.Tell() ] = xDrawObj;
4179 maObjMapId[ xDrawObj->GetObjId() ] = xDrawObj;
4182 void XclImpDrawing::ReadTxo( XclImpStream& rStrm )
4184 XclImpObjTextRef xTextData = std::make_shared<XclImpObjTextData>();
4185 maTextMap[ maDffStrm.Tell() ] = xTextData;
4187 // 1) read the TXO record
4188 xTextData->maData.ReadTxo8( rStrm );
4190 // 2) first CONTINUE with string
4191 xTextData->mxString.reset();
4192 bool bValid = true;
4193 if( xTextData->maData.mnTextLen > 0 )
4195 bValid = (rStrm.GetNextRecId() == EXC_ID_CONT) && rStrm.StartNextRecord();
4196 OSL_ENSURE( bValid, "XclImpDrawing::ReadTxo - missing CONTINUE record" );
4197 if( bValid )
4198 xTextData->mxString = std::make_shared<XclImpString>( rStrm.ReadUniString( xTextData->maData.mnTextLen ) );
4201 // 3) second CONTINUE with formatting runs
4202 if( xTextData->maData.mnFormatSize > 0 )
4204 bValid = (rStrm.GetNextRecId() == EXC_ID_CONT) && rStrm.StartNextRecord();
4205 OSL_ENSURE( bValid, "XclImpDrawing::ReadTxo - missing CONTINUE record" );
4206 if( bValid )
4207 xTextData->ReadFormats( rStrm );
4211 XclImpSheetDrawing::XclImpSheetDrawing( const XclImpRoot& rRoot, SCTAB nScTab ) :
4212 XclImpDrawing( rRoot, true ),
4213 maScUsedArea( ScAddress::INITIALIZE_INVALID )
4215 maScUsedArea.aStart.SetTab( nScTab );
4216 maScUsedArea.aEnd.SetTab( nScTab );
4219 void XclImpSheetDrawing::ReadNote( XclImpStream& rStrm )
4221 switch( GetBiff() )
4223 case EXC_BIFF2:
4224 case EXC_BIFF3:
4225 case EXC_BIFF4:
4226 case EXC_BIFF5:
4227 ReadNote3( rStrm );
4228 break;
4229 case EXC_BIFF8:
4230 ReadNote8( rStrm );
4231 break;
4232 default:
4233 DBG_ERROR_BIFF();
4237 void XclImpSheetDrawing::ReadTabChart( XclImpStream& rStrm )
4239 OSL_ENSURE_BIFF( GetBiff() >= EXC_BIFF5 );
4240 auto xChartObj = std::make_shared<XclImpChartObj>( GetRoot(), true );
4241 xChartObj->ReadChartSubStream( rStrm );
4242 // insert the chart as raw object without connected DFF data
4243 AppendRawObject( xChartObj );
4246 void XclImpSheetDrawing::ConvertObjects( XclImpDffConverter& rDffConv )
4248 if( SdrModel* pSdrModel = GetDoc().GetDrawLayer() )
4249 if( SdrPage* pSdrPage = GetSdrPage( maScUsedArea.aStart.Tab() ) )
4250 ImplConvertObjects( rDffConv, *pSdrModel, *pSdrPage );
4253 tools::Rectangle XclImpSheetDrawing::CalcAnchorRect( const XclObjAnchor& rAnchor, bool /*bDffAnchor*/ ) const
4255 return rAnchor.GetRect( GetRoot(), maScUsedArea.aStart.Tab(), MapUnit::Map100thMM );
4258 void XclImpSheetDrawing::OnObjectInserted( const XclImpDrawObjBase& rDrawObj )
4260 ScRange aScObjArea = rDrawObj.GetUsedArea( maScUsedArea.aStart.Tab() );
4261 if( aScObjArea.IsValid() )
4262 maScUsedArea.ExtendTo( aScObjArea );
4265 // private --------------------------------------------------------------------
4267 void XclImpSheetDrawing::ReadNote3( XclImpStream& rStrm )
4269 XclAddress aXclPos;
4270 rStrm >> aXclPos;
4271 sal_uInt16 nTotalLen = rStrm.ReaduInt16();
4273 ScAddress aScNotePos( ScAddress::UNINITIALIZED );
4274 if( !GetAddressConverter().ConvertAddress( aScNotePos, aXclPos, maScUsedArea.aStart.Tab(), true ) )
4275 return;
4277 sal_uInt16 nPartLen = ::std::min( nTotalLen, static_cast< sal_uInt16 >( rStrm.GetRecLeft() ) );
4278 OUStringBuffer aNoteText(rStrm.ReadRawByteString( nPartLen ));
4279 nTotalLen = nTotalLen - nPartLen;
4280 while (true)
4282 if (!nTotalLen)
4283 break;
4284 if (rStrm.GetNextRecId() != EXC_ID_NOTE)
4285 break;
4286 if (!rStrm.StartNextRecord())
4287 break;
4288 rStrm >> aXclPos;
4289 nPartLen = rStrm.ReaduInt16();
4290 OSL_ENSURE( aXclPos.mnRow == 0xFFFF, "XclImpObjectManager::ReadNote3 - missing continuation NOTE record" );
4291 if( aXclPos.mnRow == 0xFFFF )
4293 OSL_ENSURE( nPartLen <= nTotalLen, "XclImpObjectManager::ReadNote3 - string too long" );
4294 aNoteText.append(rStrm.ReadRawByteString( nPartLen ));
4295 nTotalLen = nTotalLen - ::std::min( nTotalLen, nPartLen );
4297 else
4299 // seems to be a new note, record already started -> load the note
4300 rStrm.Seek( EXC_REC_SEEK_TO_BEGIN );
4301 ReadNote( rStrm );
4302 nTotalLen = 0;
4305 ScNoteUtil::CreateNoteFromString( GetDoc(), aScNotePos, aNoteText.makeStringAndClear(), false, false );
4308 void XclImpSheetDrawing::ReadNote8( XclImpStream& rStrm )
4310 XclAddress aXclPos;
4311 sal_uInt16 nFlags, nObjId;
4312 rStrm >> aXclPos;
4313 nFlags = rStrm.ReaduInt16();
4314 nObjId = rStrm.ReaduInt16();
4316 ScAddress aScNotePos( ScAddress::UNINITIALIZED );
4317 if( GetAddressConverter().ConvertAddress( aScNotePos, aXclPos, maScUsedArea.aStart.Tab(), true ) )
4318 if( nObjId != EXC_OBJ_INVALID_ID )
4319 if( XclImpNoteObj* pNoteObj = dynamic_cast< XclImpNoteObj* >( FindDrawObj( nObjId ).get() ) )
4320 pNoteObj->SetNoteData( aScNotePos, nFlags );
4323 // The object manager =========================================================
4325 XclImpObjectManager::XclImpObjectManager( const XclImpRoot& rRoot ) :
4326 XclImpRoot( rRoot )
4328 maDefObjNames[ EXC_OBJTYPE_GROUP ] = "Group";
4329 maDefObjNames[ EXC_OBJTYPE_LINE ] = ScResId( STR_SHAPE_LINE );
4330 maDefObjNames[ EXC_OBJTYPE_RECTANGLE ] = ScResId( STR_SHAPE_RECTANGLE );
4331 maDefObjNames[ EXC_OBJTYPE_OVAL ] = ScResId( STR_SHAPE_OVAL );
4332 maDefObjNames[ EXC_OBJTYPE_ARC ] = "Arc";
4333 maDefObjNames[ EXC_OBJTYPE_CHART ] = "Chart";
4334 maDefObjNames[ EXC_OBJTYPE_TEXT ] = "Text";
4335 maDefObjNames[ EXC_OBJTYPE_BUTTON ] = ScResId( STR_FORM_BUTTON );
4336 maDefObjNames[ EXC_OBJTYPE_PICTURE ] = "Picture";
4337 maDefObjNames[ EXC_OBJTYPE_POLYGON ] = "Freeform";
4338 maDefObjNames[ EXC_OBJTYPE_CHECKBOX ] = ScResId( STR_FORM_CHECKBOX );
4339 maDefObjNames[ EXC_OBJTYPE_OPTIONBUTTON ] = ScResId( STR_FORM_OPTIONBUTTON );
4340 maDefObjNames[ EXC_OBJTYPE_EDIT ] = "Edit Box";
4341 maDefObjNames[ EXC_OBJTYPE_LABEL ] = ScResId( STR_FORM_LABEL );
4342 maDefObjNames[ EXC_OBJTYPE_DIALOG ] = "Dialog Frame";
4343 maDefObjNames[ EXC_OBJTYPE_SPIN ] = ScResId( STR_FORM_SPINNER );
4344 maDefObjNames[ EXC_OBJTYPE_SCROLLBAR ] = ScResId( STR_FORM_SCROLLBAR );
4345 maDefObjNames[ EXC_OBJTYPE_LISTBOX ] = ScResId( STR_FORM_LISTBOX );
4346 maDefObjNames[ EXC_OBJTYPE_GROUPBOX ] = ScResId( STR_FORM_GROUPBOX );
4347 maDefObjNames[ EXC_OBJTYPE_DROPDOWN ] = ScResId( STR_FORM_DROPDOWN );
4348 maDefObjNames[ EXC_OBJTYPE_NOTE ] = "Comment";
4349 maDefObjNames[ EXC_OBJTYPE_DRAWING ] = ScResId( STR_SHAPE_AUTOSHAPE );
4352 XclImpObjectManager::~XclImpObjectManager()
4356 void XclImpObjectManager::ReadMsoDrawingGroup( XclImpStream& rStrm )
4358 OSL_ENSURE_BIFF( GetBiff() == EXC_BIFF8 );
4359 // Excel continues this record with MSODRAWINGGROUP and CONTINUE records, hmm.
4360 rStrm.ResetRecord( true, EXC_ID_MSODRAWINGGROUP );
4361 maDggStrm.Seek( STREAM_SEEK_TO_END );
4362 rStrm.CopyRecordToStream( maDggStrm );
4365 XclImpSheetDrawing& XclImpObjectManager::GetSheetDrawing( SCTAB nScTab )
4367 XclImpSheetDrawingRef& rxDrawing = maSheetDrawings[ nScTab ];
4368 if( !rxDrawing )
4369 rxDrawing = std::make_shared<XclImpSheetDrawing>( GetRoot(), nScTab );
4370 return *rxDrawing;
4373 void XclImpObjectManager::ConvertObjects()
4375 // do nothing if the document does not contain a drawing layer
4376 if( !GetDoc().GetDrawLayer() )
4377 return;
4379 // get total progress bar size for all sheet drawing managers
4380 std::size_t nProgressSize = std::accumulate(maSheetDrawings.begin(), maSheetDrawings.end(), std::size_t(0),
4381 [](const std::size_t& rSum, const XclImpSheetDrawingMap::value_type& rEntry) { return rSum + rEntry.second->GetProgressSize(); });
4382 // nothing to do if progress bar is zero (no objects present)
4383 if( nProgressSize == 0 )
4384 return;
4386 XclImpDffConverter aDffConv( GetRoot(), maDggStrm );
4387 aDffConv.StartProgressBar( nProgressSize );
4388 for( auto& rEntry : maSheetDrawings )
4389 rEntry.second->ConvertObjects( aDffConv );
4391 // #i112436# don't call ScChartListenerCollection::SetDirty here,
4392 // instead use InterpretDirtyCells in ScDocument::CalcAfterLoad.
4395 OUString XclImpObjectManager::GetDefaultObjName( const XclImpDrawObjBase& rDrawObj ) const
4397 OUStringBuffer aDefName;
4398 DefObjNameMap::const_iterator aIt = maDefObjNames.find( rDrawObj.GetObjType() );
4399 if( aIt != maDefObjNames.end() )
4400 aDefName.append(aIt->second);
4401 return aDefName.append(' ').append(static_cast<sal_Int32>(rDrawObj.GetObjId())).makeStringAndClear();
4404 ScRange XclImpObjectManager::GetUsedArea( SCTAB nScTab ) const
4406 XclImpSheetDrawingMap::const_iterator aIt = maSheetDrawings.find( nScTab );
4407 if( aIt != maSheetDrawings.end() )
4408 return aIt->second->GetUsedArea();
4409 return ScRange( ScAddress::INITIALIZE_INVALID );
4412 // DFF property set helper ====================================================
4414 XclImpDffPropSet::XclImpDffPropSet( const XclImpRoot& rRoot ) :
4415 XclImpRoot( rRoot ),
4416 maDffConv( rRoot, maDummyStrm )
4420 void XclImpDffPropSet::Read( XclImpStream& rStrm )
4422 sal_uInt32 nPropSetSize;
4424 rStrm.PushPosition();
4425 rStrm.Ignore( 4 );
4426 nPropSetSize = rStrm.ReaduInt32();
4427 rStrm.PopPosition();
4429 mxMemStrm.reset( new SvMemoryStream );
4430 rStrm.CopyToStream( *mxMemStrm, 8 + nPropSetSize );
4431 mxMemStrm->Seek( STREAM_SEEK_TO_BEGIN );
4432 maDffConv.ReadPropSet( *mxMemStrm, nullptr );
4435 sal_uInt32 XclImpDffPropSet::GetPropertyValue( sal_uInt16 nPropId ) const
4437 return maDffConv.GetPropertyValue( nPropId, 0 );
4440 void XclImpDffPropSet::FillToItemSet( SfxItemSet& rItemSet ) const
4442 if( mxMemStrm )
4443 maDffConv.ApplyAttributes( *mxMemStrm, rItemSet );
4446 XclImpStream& operator>>( XclImpStream& rStrm, XclImpDffPropSet& rPropSet )
4448 rPropSet.Read( rStrm );
4449 return rStrm;
4452 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */