LibreOffice Module sc (master) 1
xiescher.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <xiescher.hxx>
21
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>
43
44#include <sfx2/objsh.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>
54#include <o3tl/safeint.hxx>
58#include <sal/log.hxx>
59
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>
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>
89
90#include <editeng/eeitem.hxx>
91#include <svx/xflclit.hxx>
92#include <sal/macros.h>
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>
102
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>
111
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>
123
124#include <namebuff.hxx>
125#include <sfx2/docfile.hxx>
126#include <memory>
127#include <numeric>
128#include <string_view>
129#include <utility>
130
131using namespace com::sun::star;
132using ::com::sun::star::uno::Any;
133using ::com::sun::star::beans::XPropertySet;
134using ::com::sun::star::uno::Exception;
135using ::com::sun::star::uno::Reference;
136using ::com::sun::star::uno::Sequence;
137using ::com::sun::star::uno::UNO_QUERY;
138using ::com::sun::star::uno::UNO_QUERY_THROW;
139using ::com::sun::star::uno::UNO_SET_THROW;
140using ::com::sun::star::beans::NamedValue;
141using ::com::sun::star::lang::XMultiServiceFactory;
142using ::com::sun::star::container::XIndexContainer;
143using ::com::sun::star::container::XNameContainer;
144using ::com::sun::star::frame::XModel;
145using ::com::sun::star::awt::XControlModel;
146using ::com::sun::star::embed::XEmbeddedObject;
147using ::com::sun::star::embed::XEmbedPersist;
148using ::com::sun::star::drawing::XControlShape;
149using ::com::sun::star::drawing::XShape;
150using ::com::sun::star::form::XFormComponent;
151using ::com::sun::star::form::XFormsSupplier;
152using ::com::sun::star::form::binding::XBindableValue;
153using ::com::sun::star::form::binding::XValueBinding;
154using ::com::sun::star::form::binding::XListEntrySink;
155using ::com::sun::star::form::binding::XListEntrySource;
156using ::com::sun::star::script::ScriptEventDescriptor;
157using ::com::sun::star::script::XEventAttacherManager;
158using ::com::sun::star::table::CellAddress;
159using ::com::sun::star::table::CellRangeAddress;
160
161// Drawing objects ============================================================
162
164 XclImpRoot( rRoot ),
165 mnObjId( EXC_OBJ_INVALID_ID ),
166 mnTab( 0 ),
167 mnObjType( EXC_OBJTYPE_UNKNOWN ),
168 mnDffShapeId( 0 ),
169 mnDffFlags( ShapeFlag::NONE ),
170 mbHasAnchor( false ),
171 mbHidden( false ),
172 mbVisible( true ),
173 mbPrintable( true ),
174 mbAreaObj( false ),
175 mbAutoMargin( true ),
176 mbSimpleMacro( true ),
177 mbProcessSdr( true ),
178 mbInsertSdr( true ),
179 mbCustomDff( false ),
180 mbNotifyMacroEventRead( false )
181{
182}
183
185{
186}
187
189{
190 XclImpDrawObjRef xDrawObj;
191
192 if( rStrm.GetRecLeft() >= 30 )
193 {
194 sal_uInt16 nObjType;
195 rStrm.Ignore( 4 );
196 nObjType = rStrm.ReaduInt16();
197 switch( nObjType )
198 {
199 case EXC_OBJTYPE_GROUP: xDrawObj= std::make_shared<XclImpGroupObj>( rRoot ); break;
200 case EXC_OBJTYPE_LINE: xDrawObj= std::make_shared<XclImpLineObj>( rRoot ); break;
201 case EXC_OBJTYPE_RECTANGLE: xDrawObj= std::make_shared<XclImpRectObj>( rRoot ); break;
202 case EXC_OBJTYPE_OVAL: xDrawObj= std::make_shared<XclImpOvalObj>( rRoot ); break;
203 case EXC_OBJTYPE_ARC: xDrawObj= std::make_shared<XclImpArcObj>( rRoot ); break;
204 case EXC_OBJTYPE_CHART: xDrawObj= std::make_shared<XclImpChartObj>( rRoot ); break;
205 case EXC_OBJTYPE_TEXT: xDrawObj= std::make_shared<XclImpTextObj>( rRoot ); break;
206 case EXC_OBJTYPE_BUTTON: xDrawObj= std::make_shared<XclImpButtonObj>( rRoot ); break;
207 case EXC_OBJTYPE_PICTURE: xDrawObj= std::make_shared<XclImpPictureObj>( rRoot ); break;
208 default:
209 SAL_WARN("sc.filter", "XclImpDrawObjBase::ReadObj3 - unknown object type 0x" << std::hex << nObjType );
211 }
212 }
213
214 if (!xDrawObj)
215 {
216 xDrawObj = std::make_shared<XclImpPhObj>(rRoot);
217 }
218
219 xDrawObj->mnTab = rRoot.GetCurrScTab();
220 xDrawObj->ImplReadObj3( rStrm );
221 return xDrawObj;
222}
223
225{
226 XclImpDrawObjRef xDrawObj;
227
228 if( rStrm.GetRecLeft() >= 30 )
229 {
230 sal_uInt16 nObjType;
231 rStrm.Ignore( 4 );
232 nObjType = rStrm.ReaduInt16();
233 switch( nObjType )
234 {
235 case EXC_OBJTYPE_GROUP: xDrawObj = std::make_shared<XclImpGroupObj>( rRoot ); break;
236 case EXC_OBJTYPE_LINE: xDrawObj = std::make_shared<XclImpLineObj>( rRoot ); break;
237 case EXC_OBJTYPE_RECTANGLE: xDrawObj = std::make_shared<XclImpRectObj>( rRoot ); break;
238 case EXC_OBJTYPE_OVAL: xDrawObj = std::make_shared<XclImpOvalObj>( rRoot ); break;
239 case EXC_OBJTYPE_ARC: xDrawObj = std::make_shared<XclImpArcObj>( rRoot ); break;
240 case EXC_OBJTYPE_CHART: xDrawObj = std::make_shared<XclImpChartObj>( rRoot ); break;
241 case EXC_OBJTYPE_TEXT: xDrawObj = std::make_shared<XclImpTextObj>( rRoot ); break;
242 case EXC_OBJTYPE_BUTTON: xDrawObj = std::make_shared<XclImpButtonObj>( rRoot ); break;
243 case EXC_OBJTYPE_PICTURE: xDrawObj = std::make_shared<XclImpPictureObj>( rRoot ); break;
244 case EXC_OBJTYPE_POLYGON: xDrawObj = std::make_shared<XclImpPolygonObj>( rRoot ); break;
245 default:
246 SAL_WARN("sc.filter", "XclImpDrawObjBase::ReadObj4 - unknown object type 0x" << std::hex << nObjType );
248 }
249 }
250
251 if (!xDrawObj)
252 {
253 xDrawObj = std::make_shared<XclImpPhObj>(rRoot);
254 }
255
256 xDrawObj->mnTab = rRoot.GetCurrScTab();
257 xDrawObj->ImplReadObj4( rStrm );
258 return xDrawObj;
259}
260
262{
263 XclImpDrawObjRef xDrawObj;
264
265 if( rStrm.GetRecLeft() >= 34 )
266 {
267 sal_uInt16 nObjType(EXC_OBJTYPE_UNKNOWN);
268 rStrm.Ignore( 4 );
269 nObjType = rStrm.ReaduInt16();
270 switch( nObjType )
271 {
272 case EXC_OBJTYPE_GROUP: xDrawObj = std::make_shared<XclImpGroupObj>( rRoot ); break;
273 case EXC_OBJTYPE_LINE: xDrawObj = std::make_shared<XclImpLineObj>( rRoot ); break;
274 case EXC_OBJTYPE_RECTANGLE: xDrawObj = std::make_shared<XclImpRectObj>( rRoot ); break;
275 case EXC_OBJTYPE_OVAL: xDrawObj = std::make_shared<XclImpOvalObj>( rRoot ); break;
276 case EXC_OBJTYPE_ARC: xDrawObj = std::make_shared<XclImpArcObj>( rRoot ); break;
277 case EXC_OBJTYPE_CHART: xDrawObj = std::make_shared<XclImpChartObj>( rRoot ); break;
278 case EXC_OBJTYPE_TEXT: xDrawObj = std::make_shared<XclImpTextObj>( rRoot ); break;
279 case EXC_OBJTYPE_BUTTON: xDrawObj = std::make_shared<XclImpButtonObj>( rRoot ); break;
280 case EXC_OBJTYPE_PICTURE: xDrawObj = std::make_shared<XclImpPictureObj>( rRoot ); break;
281 case EXC_OBJTYPE_POLYGON: xDrawObj = std::make_shared<XclImpPolygonObj>( rRoot ); break;
282 case EXC_OBJTYPE_CHECKBOX: xDrawObj = std::make_shared<XclImpCheckBoxObj>( rRoot ); break;
283 case EXC_OBJTYPE_OPTIONBUTTON: xDrawObj = std::make_shared<XclImpOptionButtonObj>( rRoot ); break;
284 case EXC_OBJTYPE_EDIT: xDrawObj = std::make_shared<XclImpEditObj>( rRoot ); break;
285 case EXC_OBJTYPE_LABEL: xDrawObj = std::make_shared<XclImpLabelObj>( rRoot ); break;
286 case EXC_OBJTYPE_DIALOG: xDrawObj = std::make_shared<XclImpDialogObj>( rRoot ); break;
287 case EXC_OBJTYPE_SPIN: xDrawObj = std::make_shared<XclImpSpinButtonObj>( rRoot ); break;
288 case EXC_OBJTYPE_SCROLLBAR: xDrawObj = std::make_shared<XclImpScrollBarObj>( rRoot ); break;
289 case EXC_OBJTYPE_LISTBOX: xDrawObj = std::make_shared<XclImpListBoxObj>( rRoot ); break;
290 case EXC_OBJTYPE_GROUPBOX: xDrawObj = std::make_shared<XclImpGroupBoxObj>( rRoot ); break;
291 case EXC_OBJTYPE_DROPDOWN: xDrawObj = std::make_shared<XclImpDropDownObj>( rRoot ); break;
292 default:
293 SAL_WARN("sc.filter", "XclImpDrawObjBase::ReadObj5 - unknown object type 0x" << std::hex << nObjType );
295 xDrawObj = std::make_shared<XclImpPhObj>( rRoot );
296 }
297 }
298
299 OSL_ENSURE(xDrawObj, "object import failed");
300
301 if (xDrawObj)
302 {
303 xDrawObj->mnTab = rRoot.GetCurrScTab();
304 xDrawObj->ImplReadObj5( rStrm );
305 }
306 return xDrawObj;
307}
308
310{
311 XclImpDrawObjRef xDrawObj;
312
313 if( rStrm.GetRecLeft() >= 10 )
314 {
315 sal_uInt16 nSubRecId(0), nSubRecSize(0), nObjType(0);
316 nSubRecId = rStrm.ReaduInt16();
317 nSubRecSize = rStrm.ReaduInt16();
318 nObjType = rStrm.ReaduInt16();
319 OSL_ENSURE( nSubRecId == EXC_ID_OBJCMO, "XclImpDrawObjBase::ReadObj8 - OBJCMO subrecord expected" );
320 if( (nSubRecId == EXC_ID_OBJCMO) && (nSubRecSize >= 6) )
321 {
322 switch( nObjType )
323 {
324 // in BIFF8, all simple objects support text
325 case EXC_OBJTYPE_LINE:
326 case EXC_OBJTYPE_ARC:
327 xDrawObj = std::make_shared<XclImpTextObj>( rRoot );
328 // lines and arcs may be 2-dimensional
329 xDrawObj->SetAreaObj( false );
330 break;
331
332 // in BIFF8, all simple objects support text
334 case EXC_OBJTYPE_OVAL:
337 case EXC_OBJTYPE_TEXT:
338 xDrawObj = std::make_shared<XclImpTextObj>( rRoot );
339 break;
340
341 case EXC_OBJTYPE_GROUP: xDrawObj = std::make_shared<XclImpGroupObj>( rRoot ); break;
342 case EXC_OBJTYPE_CHART: xDrawObj = std::make_shared<XclImpChartObj>( rRoot ); break;
343 case EXC_OBJTYPE_BUTTON: xDrawObj = std::make_shared<XclImpButtonObj>( rRoot ); break;
344 case EXC_OBJTYPE_PICTURE: xDrawObj = std::make_shared<XclImpPictureObj>( rRoot ); break;
345 case EXC_OBJTYPE_CHECKBOX: xDrawObj = std::make_shared<XclImpCheckBoxObj>( rRoot ); break;
346 case EXC_OBJTYPE_OPTIONBUTTON: xDrawObj = std::make_shared<XclImpOptionButtonObj>( rRoot ); break;
347 case EXC_OBJTYPE_EDIT: xDrawObj = std::make_shared<XclImpEditObj>( rRoot ); break;
348 case EXC_OBJTYPE_LABEL: xDrawObj = std::make_shared<XclImpLabelObj>( rRoot ); break;
349 case EXC_OBJTYPE_DIALOG: xDrawObj = std::make_shared<XclImpDialogObj>( rRoot ); break;
350 case EXC_OBJTYPE_SPIN: xDrawObj = std::make_shared<XclImpSpinButtonObj>( rRoot ); break;
351 case EXC_OBJTYPE_SCROLLBAR: xDrawObj = std::make_shared<XclImpScrollBarObj>( rRoot ); break;
352 case EXC_OBJTYPE_LISTBOX: xDrawObj = std::make_shared<XclImpListBoxObj>( rRoot ); break;
353 case EXC_OBJTYPE_GROUPBOX: xDrawObj = std::make_shared<XclImpGroupBoxObj>( rRoot ); break;
354 case EXC_OBJTYPE_DROPDOWN: xDrawObj = std::make_shared<XclImpDropDownObj>( rRoot ); break;
355 case EXC_OBJTYPE_NOTE: xDrawObj = std::make_shared<XclImpNoteObj>( rRoot ); break;
356
357 default:
358 SAL_WARN("sc.filter", "XclImpDrawObjBase::ReadObj8 - unknown object type 0x" << std::hex << nObjType );
360 }
361 }
362 }
363
364 if (!xDrawObj) //ensure placeholder for unknown or broken records
365 {
366 SAL_WARN( "sc.filter", "XclImpDrawObjBase::ReadObj8 import failed, substituting placeholder");
367 xDrawObj = std::make_shared<XclImpPhObj>( rRoot );
368 }
369
370 xDrawObj->mnTab = rRoot.GetCurrScTab();
371 xDrawObj->ImplReadObj8( rStrm );
372 return xDrawObj;
373}
374
376{
377 maAnchor = rAnchor;
378 mbHasAnchor = true;
379}
380
382{
383 return maDffRect;
384}
385
387 const DffObjData& rDffObjData, const OUString& rObjName, const OUString& rHyperlink,
388 bool bVisible, bool bAutoMargin )
389{
390 mnDffShapeId = rDffObjData.nShapeId;
391 mnDffFlags = rDffObjData.nSpFlags;
392 maObjName = rObjName;
393 maHyperlink = rHyperlink;
395 mbAutoMargin = bAutoMargin;
396 maDffRect = rDffObjData.aChildAnchor;
397}
398
400{
401 /* #i51348# Always return a non-empty name. Create English
402 default names depending on the object type. This is not implemented as
403 virtual functions in derived classes, as class type and object type may
404 not match. */
405 return maObjName.isEmpty() ? GetObjectManager().GetDefaultObjName(*this) : maObjName;
406}
407
409{
410 return mbHasAnchor ? &maAnchor : nullptr;
411}
412
413bool XclImpDrawObjBase::IsValidSize( const tools::Rectangle& rAnchorRect ) const
414{
415 // XclObjAnchor rounds up the width, width of 3 is the result of an Excel width of 0
416 return mbAreaObj ?
417 ((rAnchorRect.GetWidth() > 3) && (rAnchorRect.GetHeight() > 1)) :
418 ((rAnchorRect.GetWidth() > 3) || (rAnchorRect.GetHeight() > 1));
419}
420
422{
424 // #i44077# object inserted -> update used area for OLE object import
425 if( mbHasAnchor && GetAddressConverter().ConvertRange( aScUsedArea, maAnchor, nScTab, nScTab, false ) )
426 {
427 // reduce range, if object ends directly on borders between two columns or rows
428 if( (maAnchor.mnRX == 0) && (aScUsedArea.aStart.Col() < aScUsedArea.aEnd.Col()) )
429 aScUsedArea.aEnd.IncCol( -1 );
430 if( (maAnchor.mnBY == 0) && (aScUsedArea.aStart.Row() < aScUsedArea.aEnd.Row()) )
431 aScUsedArea.aEnd.IncRow( -1 );
432 }
433 return aScUsedArea;
434}
435
437{
438 return DoGetProgressSize();
439}
440
442{
444 if( bIsDff && !mbCustomDff )
445 {
446 rDffConv.Progress( GetProgressSize() );
447 }
448 else
449 {
450 xSdrObj = DoCreateSdrObj( rDffConv, rAnchorRect );
451
452 //added for exporting OCX control
453 /* mnObjType value set should be as below table:
454 0x0000 Group 0x0001 Line
455 0x0002 Rectangle 0x0003 Oval
456 0x0004 Arc 0x0005 Chart
457 0x0006 Text 0x0009 Polygon
458 +-----------------------------------------------------+
459 OCX ==>| 0x0008 Picture |
460 +-----------------------------------------------------+
461 | 0x0007 Button |
462 | 0x000B Checkbox 0x000C Radio button |
463 | 0x000D Edit box 0x000E Label |
464 TBX ==> | 0x000F Dialog box 0x0010 Spin control |
465 | 0x0011 Scrollbar 0x0012 List |
466 | 0x0013 Group box 0x0014 Dropdown list |
467 +-----------------------------------------------------+
468 0x0019 Note 0x001E OfficeArt object
469 */
470 if( xSdrObj && xSdrObj->IsUnoObj() &&
471 ( (mnObjType < 25 && mnObjType > 10) || mnObjType == 7 || mnObjType == 8 ) )
472 {
473 SdrUnoObj* pSdrUnoObj = dynamic_cast< SdrUnoObj* >( xSdrObj.get() );
474 if( pSdrUnoObj != nullptr )
475 {
476 const Reference< XControlModel >& xCtrlModel = pSdrUnoObj->GetUnoControlModel();
477 Reference< XPropertySet > xPropSet(xCtrlModel,UNO_QUERY);
478 static constexpr OUStringLiteral sPropertyName(u"ControlTypeinMSO");
479
480 enum { eCreateFromOffice = 0, eCreateFromMSTBXControl, eCreateFromMSOCXControl };
481
482 if( mnObjType == 7 || (mnObjType < 25 && mnObjType > 10) )//TBX
483 {
484 try
485 {
486 //Need summary type for export. Detail type(checkbox, button ...) has been contained by mnObjType
487 const sal_Int16 nTBXControlType = eCreateFromMSTBXControl ;
488 xPropSet->setPropertyValue(sPropertyName, Any(nTBXControlType));
489 }
490 catch(const Exception&)
491 {
492 SAL_WARN("sc.filter", "XclImpDrawObjBase::CreateSdrObject, this control can't be set the property ControlTypeinMSO!");
493 }
494 }
495 if( mnObjType == 8 )//OCX
496 {
497 //Need summary type for export
498 static constexpr OUStringLiteral sObjIdPropertyName(u"ObjIDinMSO");
499 const XclImpPictureObj* const pObj = dynamic_cast< const XclImpPictureObj* const >(this);
500 if( pObj != nullptr && pObj->IsOcxControl() )
501 {
502 try
503 {
504 const sal_Int16 nOCXControlType = eCreateFromMSOCXControl;
505 xPropSet->setPropertyValue(sPropertyName, Any(nOCXControlType));
506 //Detail type(checkbox, button ...)
507 xPropSet->setPropertyValue(sObjIdPropertyName, Any(sal_uInt16(mnObjId)));
508 }
509 catch(const Exception&)
510 {
511 SAL_WARN("sc.filter", "XclImpDrawObjBase::CreateSdrObject, this control can't be set the property ObjIDinMSO!");
512 }
513 }
514 }
515
516 }
517 }
518 }
519 return xSdrObj;
520}
521
523{
525 return;
526 SfxObjectShell* pDocShell = GetDocShell();
527 if (!pDocShell)
528 return;
531}
532
534{
535 // default: front layer, derived classes may have to set other layer in DoPreProcessSdrObj()
536 rSdrObj.NbcSetLayer( SC_LAYER_FRONT );
537
538 // set object name (GetObjName() will always return a non-empty name)
539 rSdrObj.SetName( GetObjName() );
540
541 // #i39167# full width for all objects regardless of horizontal alignment
543
544 // automatic text margin
545 if( mbAutoMargin )
546 {
547 sal_Int32 nMargin = rDffConv.GetDefaultTextMargin();
548 rSdrObj.SetMergedItem( makeSdrTextLeftDistItem( nMargin ) );
549 rSdrObj.SetMergedItem( makeSdrTextRightDistItem( nMargin ) );
550 rSdrObj.SetMergedItem( makeSdrTextUpperDistItem( nMargin ) );
551 rSdrObj.SetMergedItem( makeSdrTextLowerDistItem( nMargin ) );
552 }
553
554 // macro and hyperlink
555 // removed oracle/sun check for mbSimpleMacro ( no idea what its for )
556 if (!maMacroName.isEmpty())
557 {
558 if( ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( &rSdrObj, true ) )
559 {
560 OUString sMacro = XclTools::GetSbMacroUrl(maMacroName, GetDocShell());
561 if (!sMacro.isEmpty())
563 pInfo->SetMacro(sMacro);
564 }
565 }
566 if (!maHyperlink.isEmpty())
567 rSdrObj.setHyperlink(maHyperlink);
568
569 // call virtual function for object type specific processing
570 DoPreProcessSdrObj( rDffConv, rSdrObj );
571}
572
574{
575 // call virtual function for object type specific processing
576 DoPostProcessSdrObj( rDffConv, rSdrObj );
577}
578
579// protected ------------------------------------------------------------------
580
581void XclImpDrawObjBase::ReadName5( XclImpStream& rStrm, sal_uInt16 nNameLen )
582{
583 maObjName.clear();
584 if( nNameLen > 0 )
585 {
586 // name length field is repeated before the name
587 maObjName = rStrm.ReadByteString( false );
588 // skip padding byte for word boundaries
589 if( rStrm.GetRecPos() & 1 ) rStrm.Ignore( 1 );
590 }
591}
592
593void XclImpDrawObjBase::ReadMacro3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
594{
595 maMacroName.clear();
596 rStrm.Ignore( nMacroSize );
597 // skip padding byte for word boundaries, not contained in nMacroSize
598 if( rStrm.GetRecPos() & 1 ) rStrm.Ignore( 1 );
599}
600
601void XclImpDrawObjBase::ReadMacro4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
602{
603 maMacroName.clear();
604 rStrm.Ignore( nMacroSize );
605}
606
607void XclImpDrawObjBase::ReadMacro5( XclImpStream& rStrm, sal_uInt16 nMacroSize )
608{
609 maMacroName.clear();
610 rStrm.Ignore( nMacroSize );
611}
612
614{
615 maMacroName.clear();
616 if( rStrm.GetRecLeft() <= 6 )
617 return;
618
619 // macro is stored in a tNameXR token containing a link to a defined name
620 sal_uInt16 nFmlaSize;
621 nFmlaSize = rStrm.ReaduInt16();
622 rStrm.Ignore( 4 );
623 OSL_ENSURE( nFmlaSize == 7, "XclImpDrawObjBase::ReadMacro - unexpected formula size" );
624 if( nFmlaSize == 7 )
625 {
626 sal_uInt8 nTokenId;
627 sal_uInt16 nExtSheet, nExtName;
628 nTokenId = rStrm.ReaduInt8();
629 nExtSheet = rStrm.ReaduInt16();
630 nExtName = rStrm.ReaduInt16();
632 "XclImpDrawObjBase::ReadMacro - tNameXR token expected" );
634 maMacroName = GetLinkManager().GetMacroName( nExtSheet, nExtName );
635 }
636}
637
638void XclImpDrawObjBase::ConvertLineStyle( SdrObject& rSdrObj, const XclObjLineData& rLineData ) const
639{
640 if( rLineData.IsAuto() )
641 {
642 XclObjLineData aAutoData;
643 aAutoData.mnAuto = 0;
644 ConvertLineStyle( rSdrObj, aAutoData );
645 }
646 else
647 {
648 tools::Long nLineWidth = 35 * ::std::min( rLineData.mnWidth, EXC_OBJ_LINE_THICK );
650 rSdrObj.SetMergedItem( XLineColorItem( OUString(), GetPalette().GetColor( rLineData.mnColorIdx ) ) );
651 rSdrObj.SetMergedItem( XLineJointItem( css::drawing::LineJoint_MITER ) );
652
653 sal_uLong nDotLen = ::std::max< sal_uLong >( 70 * rLineData.mnWidth, 35 );
654 sal_uLong nDashLen = 3 * nDotLen;
655 sal_uLong nDist = 2 * nDotLen;
656
657 switch( rLineData.mnStyle )
658 {
659 default:
661 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_SOLID ) );
662 break;
664 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_DASH ) );
665 rSdrObj.SetMergedItem( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECT, 0, nDotLen, 1, nDashLen, nDist ) ) );
666 break;
667 case EXC_OBJ_LINE_DOT:
668 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_DASH ) );
669 rSdrObj.SetMergedItem( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECT, 1, nDotLen, 0, nDashLen, nDist ) ) );
670 break;
672 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_DASH ) );
673 rSdrObj.SetMergedItem( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECT, 1, nDotLen, 1, nDashLen, nDist ) ) );
674 break;
676 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_DASH ) );
677 rSdrObj.SetMergedItem( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECT, 2, nDotLen, 1, nDashLen, nDist ) ) );
678 break;
680 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_SOLID ) );
681 rSdrObj.SetMergedItem( XLineTransparenceItem( 50 ) );
682 break;
684 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_SOLID ) );
685 rSdrObj.SetMergedItem( XLineTransparenceItem( 25 ) );
686 break;
688 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_SOLID ) );
689 rSdrObj.SetMergedItem( XLineTransparenceItem( 75 ) );
690 break;
692 rSdrObj.SetMergedItem( XLineStyleItem( drawing::LineStyle_NONE ) );
693 break;
694 }
695 }
696}
697
698void XclImpDrawObjBase::ConvertFillStyle( SdrObject& rSdrObj, const XclObjFillData& rFillData ) const
699{
700 if( rFillData.IsAuto() )
701 {
702 XclObjFillData aAutoData;
703 aAutoData.mnAuto = 0;
704 ConvertFillStyle( rSdrObj, aAutoData );
705 }
706 else if( rFillData.mnPattern == EXC_PATT_NONE )
707 {
708 rSdrObj.SetMergedItem( XFillStyleItem( drawing::FillStyle_NONE ) );
709 }
710 else
711 {
712 Color aPattColor = GetPalette().GetColor( rFillData.mnPattColorIdx );
713 Color aBackColor = GetPalette().GetColor( rFillData.mnBackColorIdx );
714 if( (rFillData.mnPattern == EXC_PATT_SOLID) || (aPattColor == aBackColor) )
715 {
716 rSdrObj.SetMergedItem( XFillStyleItem( drawing::FillStyle_SOLID ) );
717 rSdrObj.SetMergedItem( XFillColorItem( OUString(), aPattColor ) );
718 }
719 else
720 {
721 static const sal_uInt8 sppnPatterns[][ 8 ] =
722 {
723 { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 },
724 { 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD },
725 { 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 },
726 { 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00 },
727 { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC },
728 { 0x33, 0x66, 0xCC, 0x99, 0x33, 0x66, 0xCC, 0x99 },
729 { 0xCC, 0x66, 0x33, 0x99, 0xCC, 0x66, 0x33, 0x99 },
730 { 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33 },
731 { 0xCC, 0xFF, 0x33, 0xFF, 0xCC, 0xFF, 0x33, 0xFF },
732 { 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 },
733 { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 },
734 { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 },
735 { 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 },
736 { 0xFF, 0x11, 0x11, 0x11, 0xFF, 0x11, 0x11, 0x11 },
737 { 0xAA, 0x44, 0xAA, 0x11, 0xAA, 0x44, 0xAA, 0x11 },
738 { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 },
739 { 0x80, 0x00, 0x08, 0x00, 0x80, 0x00, 0x08, 0x00 }
740 };
741 const sal_uInt8* const pnPattern = sppnPatterns[std::min<size_t>(rFillData.mnPattern - 2, SAL_N_ELEMENTS(sppnPatterns) - 1)];
742 // create 2-colored 8x8 DIB
743 SvMemoryStream aMemStrm;
744 aMemStrm.WriteUInt32( 12 ).WriteInt16( 8 ).WriteInt16( 8 ).WriteUInt16( 1 ).WriteUInt16( 1 );
745 aMemStrm.WriteUChar( 0xFF ).WriteUChar( 0xFF ).WriteUChar( 0xFF );
746 aMemStrm.WriteUChar( 0x00 ).WriteUChar( 0x00 ).WriteUChar( 0x00 );
747 for( size_t nIdx = 0; nIdx < 8; ++nIdx )
748 aMemStrm.WriteUInt32( pnPattern[ nIdx ] ); // 32-bit little-endian
749 aMemStrm.Seek( STREAM_SEEK_TO_BEGIN );
750 Bitmap aBitmap;
751 (void)ReadDIB(aBitmap, aMemStrm, false);
752
753 XOBitmap aXOBitmap(( BitmapEx(aBitmap) ));
754 aXOBitmap.Bitmap2Array();
755 if( aXOBitmap.GetBackgroundColor() == COL_BLACK )
756 ::std::swap( aPattColor, aBackColor );
757 aXOBitmap.SetPixelColor( aPattColor );
758 aXOBitmap.SetBackgroundColor( aBackColor );
759 aXOBitmap.Array2Bitmap();
760 aBitmap = aXOBitmap.GetBitmap().GetBitmap();
761
762 rSdrObj.SetMergedItem(XFillStyleItem(drawing::FillStyle_BITMAP));
763 rSdrObj.SetMergedItem(XFillBitmapItem(OUString(), Graphic(BitmapEx(aBitmap))));
764 }
765 }
766}
767
768void XclImpDrawObjBase::ConvertFrameStyle( SdrObject& rSdrObj, sal_uInt16 nFrameFlags ) const
769{
770 if( ::get_flag( nFrameFlags, EXC_OBJ_FRAME_SHADOW ) )
771 {
772 rSdrObj.SetMergedItem( makeSdrShadowItem( true ) );
773 rSdrObj.SetMergedItem( makeSdrShadowXDistItem( 35 ) );
774 rSdrObj.SetMergedItem( makeSdrShadowYDistItem( 35 ) );
776 }
777}
778
780{
781 Color aColor( COL_TRANSPARENT );
782 if( rLineData.IsAuto() )
783 {
784 XclObjLineData aAutoData;
785 aAutoData.mnAuto = 0;
786 aColor = GetSolidLineColor( aAutoData );
787 }
788 else if( rLineData.mnStyle != EXC_OBJ_LINE_NONE )
789 {
790 aColor = GetPalette().GetColor( rLineData.mnColorIdx );
791 }
792 return aColor;
793}
794
796{
797 Color aColor( COL_TRANSPARENT );
798 if( rFillData.IsAuto() )
799 {
800 XclObjFillData aAutoData;
801 aAutoData.mnAuto = 0;
802 aColor = GetSolidFillColor( aAutoData );
803 }
804 else if( rFillData.mnPattern != EXC_PATT_NONE )
805 {
806 Color aPattColor = GetPalette().GetColor( rFillData.mnPattColorIdx );
807 Color aBackColor = GetPalette().GetColor( rFillData.mnBackColorIdx );
808 aColor = XclTools::GetPatternColor( aPattColor, aBackColor, rFillData.mnPattern );
809 }
810 return aColor;
811}
812
814{
815}
816
818{
819}
820
821void XclImpDrawObjBase::DoReadObj5( XclImpStream&, sal_uInt16, sal_uInt16 )
822{
823}
824
825void XclImpDrawObjBase::DoReadObj8SubRec( XclImpStream&, sal_uInt16, sal_uInt16 )
826{
827}
828
830{
831 return 1;
832}
833
835{
836 rDffConv.Progress( GetProgressSize() );
837 return nullptr;
838}
839
841{
842 // trace if object is not printable
843 if( !IsPrintable() )
845}
846
848{
849}
850
852{
853 // back to offset 4 (ignore object count field)
854 rStrm.Seek( 4 );
855
856 sal_uInt16 nObjFlags, nMacroSize;
857 mnObjType = rStrm.ReaduInt16();
858 mnObjId = rStrm.ReaduInt16();
859 nObjFlags = rStrm.ReaduInt16();
860 rStrm >> maAnchor;
861 nMacroSize = rStrm.ReaduInt16();
862 rStrm.Ignore( 2 );
863
864 mbHasAnchor = true;
865 mbHidden = ::get_flag( nObjFlags, EXC_OBJ_HIDDEN );
866 mbVisible = ::get_flag( nObjFlags, EXC_OBJ_VISIBLE );
867 DoReadObj3( rStrm, nMacroSize );
868}
869
871{
872 // back to offset 4 (ignore object count field)
873 rStrm.Seek( 4 );
874
875 sal_uInt16 nObjFlags, nMacroSize;
876 mnObjType = rStrm.ReaduInt16();
877 mnObjId = rStrm.ReaduInt16();
878 nObjFlags = rStrm.ReaduInt16();
879 rStrm >> maAnchor;
880 nMacroSize = rStrm.ReaduInt16();
881 rStrm.Ignore( 2 );
882
883 mbHasAnchor = true;
884 mbHidden = ::get_flag( nObjFlags, EXC_OBJ_HIDDEN );
885 mbVisible = ::get_flag( nObjFlags, EXC_OBJ_VISIBLE );
887 DoReadObj4( rStrm, nMacroSize );
888}
889
891{
892 // back to offset 4 (ignore object count field)
893 rStrm.Seek( 4 );
894
895 sal_uInt16 nObjFlags, nMacroSize, nNameLen;
896 mnObjType = rStrm.ReaduInt16();
897 mnObjId = rStrm.ReaduInt16();
898 nObjFlags = rStrm.ReaduInt16();
899 rStrm >> maAnchor;
900 nMacroSize = rStrm.ReaduInt16();
901 rStrm.Ignore( 2 );
902 nNameLen = rStrm.ReaduInt16();
903 rStrm.Ignore( 2 );
904
905 mbHasAnchor = true;
906 mbHidden = ::get_flag( nObjFlags, EXC_OBJ_HIDDEN );
907 mbVisible = ::get_flag( nObjFlags, EXC_OBJ_VISIBLE );
909 DoReadObj5( rStrm, nNameLen, nMacroSize );
910}
911
913{
914 // back to beginning
916
917 bool bLoop = true;
918 while (bLoop)
919 {
920 if (rStrm.GetRecLeft() < 4)
921 break;
922
923 sal_uInt16 nSubRecId = rStrm.ReaduInt16();
924 sal_uInt16 nSubRecSize = rStrm.ReaduInt16();
925 rStrm.PushPosition();
926 // sometimes the last subrecord has an invalid length (OBJLBSDATA) -> min()
927 nSubRecSize = static_cast< sal_uInt16 >( ::std::min< std::size_t >( nSubRecSize, rStrm.GetRecLeft() ) );
928
929 switch( nSubRecId )
930 {
931 case EXC_ID_OBJCMO:
932 OSL_ENSURE( rStrm.GetRecPos() == 4, "XclImpDrawObjBase::ImplReadObj8 - unexpected OBJCMO subrecord" );
933 if( (rStrm.GetRecPos() == 4) && (nSubRecSize >= 6) )
934 {
935 sal_uInt16 nObjFlags;
936 mnObjType = rStrm.ReaduInt16();
937 mnObjId = rStrm.ReaduInt16( );
938 nObjFlags = rStrm.ReaduInt16( );
940 }
941 break;
942 case EXC_ID_OBJMACRO:
943 ReadMacro8( rStrm );
944 break;
945 case EXC_ID_OBJEND:
946 bLoop = false;
947 break;
948 default:
949 DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
950 }
951
952 rStrm.PopPosition();
953 rStrm.Ignore( nSubRecSize );
954 }
955
956 /* Call DoReadObj8SubRec() with EXC_ID_OBJEND for further stream
957 processing (e.g. charts), even if the OBJEND subrecord is missing. */
959
960 /* Pictures that Excel reads from BIFF5 and writes to BIFF8 still have the
961 IMGDATA record following the OBJ record (but they use the image data
962 stored in DFF). The IMGDATA record may be continued by several CONTINUE
963 records. But the last CONTINUE record may be in fact an MSODRAWING
964 record that contains the DFF data of the next drawing object! So we
965 have to skip just enough CONTINUE records to look at the next
966 MSODRAWING/CONTINUE record. */
967 if( !((rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord()) )
968 return;
969
970 rStrm.Ignore( 4 );
971 sal_uInt32 nDataSize = rStrm.ReaduInt32();
972 nDataSize -= rStrm.GetRecLeft();
973 // skip following CONTINUE records until IMGDATA ends
974 while (true)
975 {
976 if (!nDataSize)
977 break;
978 if (rStrm.GetNextRecId() != EXC_ID_CONT)
979 break;
980 if (!rStrm.StartNextRecord())
981 break;
982 OSL_ENSURE( nDataSize >= rStrm.GetRecLeft(), "XclImpDrawObjBase::ImplReadObj8 - CONTINUE too long" );
983 nDataSize -= ::std::min< sal_uInt32 >( rStrm.GetRecLeft(), nDataSize );
984 }
985 OSL_ENSURE( nDataSize == 0, "XclImpDrawObjBase::ImplReadObj8 - missing CONTINUE records" );
986 // next record may be MSODRAWING or CONTINUE or anything else
987}
988
990{
991 if( !mObjs.empty() )
992 if( XclImpGroupObj* pGroupObj = dynamic_cast< XclImpGroupObj* >( mObjs.back().get() ) )
993 if( pGroupObj->TryInsert( xDrawObj ) )
994 return;
995 mObjs.push_back( xDrawObj );
996}
997
999{
1000 return std::accumulate(mObjs.begin(), mObjs.end(), std::size_t(0),
1001 [](const std::size_t& rSum, const XclImpDrawObjRef& rxObj) { return rSum + rxObj->GetProgressSize(); });
1002}
1003
1005 XclImpDrawObjBase( rRoot )
1006{
1007 SetProcessSdrObj( false );
1008}
1009
1011 XclImpDrawObjBase( rRoot ),
1012 mnFirstUngrouped( 0 )
1013{
1014}
1015
1017{
1018 if( xDrawObj->GetObjId() == mnFirstUngrouped )
1019 return false;
1020 // insert into own list or into nested group
1021 maChildren.InsertGrouped( xDrawObj );
1022 return true;
1023}
1024
1025void XclImpGroupObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1026{
1027 rStrm.Ignore( 4 );
1028 mnFirstUngrouped = rStrm.ReaduInt16();
1029 rStrm.Ignore( 16 );
1030 ReadMacro3( rStrm, nMacroSize );
1031}
1032
1033void XclImpGroupObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1034{
1035 rStrm.Ignore( 4 );
1036 mnFirstUngrouped = rStrm.ReaduInt16();
1037 rStrm.Ignore( 16 );
1038 ReadMacro4( rStrm, nMacroSize );
1039}
1040
1041void XclImpGroupObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1042{
1043 rStrm.Ignore( 4 );
1044 mnFirstUngrouped = rStrm.ReaduInt16();
1045 rStrm.Ignore( 16 );
1046 ReadName5( rStrm, nNameLen );
1047 ReadMacro5( rStrm, nMacroSize );
1048}
1049
1051{
1053}
1054
1056{
1058 new SdrObjGroup(
1059 *GetDoc().GetDrawLayer()));
1060 // child objects in BIFF2-BIFF5 have absolute size, not needed to pass own anchor rectangle
1061 SdrObjList& rObjList = *xSdrObj->GetSubList(); // SdrObjGroup always returns existing sublist
1062 for( const auto& rxChild : maChildren )
1063 rDffConv.ProcessObject( rObjList, *rxChild );
1064 rDffConv.Progress();
1065 return xSdrObj;
1066}
1067
1069 XclImpDrawObjBase( rRoot ),
1070 mnArrows( 0 ),
1071 mnStartPoint( EXC_OBJ_LINE_TL )
1072{
1073 SetAreaObj( false );
1074}
1075
1076void XclImpLineObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1077{
1078 rStrm >> maLineData;
1079 mnArrows = rStrm.ReaduInt16();
1080 mnStartPoint = rStrm.ReaduInt8();
1081 rStrm.Ignore( 1 );
1082 ReadMacro3( rStrm, nMacroSize );
1083}
1084
1085void XclImpLineObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1086{
1087 rStrm >> maLineData;
1088 mnArrows = rStrm.ReaduInt16();
1089 mnStartPoint = rStrm.ReaduInt8();
1090 rStrm.Ignore( 1 );
1091 ReadMacro4( rStrm, nMacroSize );
1092}
1093
1094void XclImpLineObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1095{
1096 rStrm >> maLineData;
1097 mnArrows = rStrm.ReaduInt16();
1098 mnStartPoint = rStrm.ReaduInt8();
1099 rStrm.Ignore( 1 );
1100 ReadName5( rStrm, nNameLen );
1101 ReadMacro5( rStrm, nMacroSize );
1102}
1103
1105{
1106 ::basegfx::B2DPolygon aB2DPolygon;
1107 switch( mnStartPoint )
1108 {
1109 default:
1110 case EXC_OBJ_LINE_TL:
1111 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Top() ) );
1112 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Bottom() ) );
1113 break;
1114 case EXC_OBJ_LINE_TR:
1115 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Top() ) );
1116 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Bottom() ) );
1117 break;
1118 case EXC_OBJ_LINE_BR:
1119 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Bottom() ) );
1120 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Top() ) );
1121 break;
1122 case EXC_OBJ_LINE_BL:
1123 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Left(), rAnchorRect.Bottom() ) );
1124 aB2DPolygon.append( ::basegfx::B2DPoint( rAnchorRect.Right(), rAnchorRect.Top() ) );
1125 break;
1126 }
1128 new SdrPathObj(
1129 *GetDoc().GetDrawLayer(),
1130 SdrObjKind::Line,
1131 ::basegfx::B2DPolyPolygon(aB2DPolygon)));
1132 ConvertLineStyle( *xSdrObj, maLineData );
1133
1134 // line ends
1135 sal_uInt8 nArrowType = ::extract_value< sal_uInt8 >( mnArrows, 0, 4 );
1136 bool bLineStart = false;
1137 bool bLineEnd = false;
1138 bool bFilled = false;
1139 switch( nArrowType )
1140 {
1141 case EXC_OBJ_ARROW_OPEN: bLineStart = false; bLineEnd = true; bFilled = false; break;
1142 case EXC_OBJ_ARROW_OPENBOTH: bLineStart = true; bLineEnd = true; bFilled = false; break;
1143 case EXC_OBJ_ARROW_FILLED: bLineStart = false; bLineEnd = true; bFilled = true; break;
1144 case EXC_OBJ_ARROW_FILLEDBOTH: bLineStart = true; bLineEnd = true; bFilled = true; break;
1145 }
1146 if( bLineStart || bLineEnd )
1147 {
1148 sal_uInt8 nArrowWidth = ::extract_value< sal_uInt8 >( mnArrows, 4, 4 );
1149 double fArrowWidth = 3.0;
1150 switch( nArrowWidth )
1151 {
1152 case EXC_OBJ_ARROW_NARROW: fArrowWidth = 2.0; break;
1153 case EXC_OBJ_ARROW_MEDIUM: fArrowWidth = 3.0; break;
1154 case EXC_OBJ_ARROW_WIDE: fArrowWidth = 5.0; break;
1155 }
1156
1157 sal_uInt8 nArrowLength = ::extract_value< sal_uInt8 >( mnArrows, 8, 4 );
1158 double fArrowLength = 3.0;
1159 switch( nArrowLength )
1160 {
1161 case EXC_OBJ_ARROW_NARROW: fArrowLength = 2.5; break;
1162 case EXC_OBJ_ARROW_MEDIUM: fArrowLength = 3.5; break;
1163 case EXC_OBJ_ARROW_WIDE: fArrowLength = 6.0; break;
1164 }
1165
1166 ::basegfx::B2DPolygon aArrowPoly;
1167#define EXC_ARROW_POINT( x, y ) ::basegfx::B2DPoint( fArrowWidth * (x), fArrowLength * (y) )
1168 if( bFilled )
1169 {
1170 aArrowPoly.append( EXC_ARROW_POINT( 0, 100 ) );
1171 aArrowPoly.append( EXC_ARROW_POINT( 50, 0 ) );
1172 aArrowPoly.append( EXC_ARROW_POINT( 100, 100 ) );
1173 }
1174 else
1175 {
1177 aArrowPoly.append( EXC_ARROW_POINT( 50, 0 ) );
1178 aArrowPoly.append( EXC_ARROW_POINT( 100, 100 - 3 * nLineWidth ) );
1179 aArrowPoly.append( EXC_ARROW_POINT( 100 - 5 * nLineWidth, 100 ) );
1180 aArrowPoly.append( EXC_ARROW_POINT( 50, 12 * nLineWidth ) );
1181 aArrowPoly.append( EXC_ARROW_POINT( 5 * nLineWidth, 100 ) );
1182 aArrowPoly.append( EXC_ARROW_POINT( 0, 100 - 3 * nLineWidth ) );
1183 }
1184#undef EXC_ARROW_POINT
1185
1186 ::basegfx::B2DPolyPolygon aArrowPolyPoly( aArrowPoly );
1187 tools::Long nWidth = static_cast< tools::Long >( 125 * fArrowWidth );
1188 if( bLineStart )
1189 {
1190 xSdrObj->SetMergedItem( XLineStartItem( OUString(), aArrowPolyPoly ) );
1191 xSdrObj->SetMergedItem( XLineStartWidthItem( nWidth ) );
1192 xSdrObj->SetMergedItem( XLineStartCenterItem( false ) );
1193 }
1194 if( bLineEnd )
1195 {
1196 xSdrObj->SetMergedItem( XLineEndItem( OUString(), aArrowPolyPoly ) );
1197 xSdrObj->SetMergedItem( XLineEndWidthItem( nWidth ) );
1198 xSdrObj->SetMergedItem( XLineEndCenterItem( false ) );
1199 }
1200 }
1201 rDffConv.Progress();
1202 return xSdrObj;
1203}
1204
1206 XclImpDrawObjBase( rRoot ),
1207 mnFrameFlags( 0 )
1208{
1209 SetAreaObj( true );
1210}
1211
1213{
1215 mnFrameFlags = rStrm.ReaduInt16();
1216}
1217
1219{
1220 ConvertLineStyle( rSdrObj, maLineData );
1221 ConvertFillStyle( rSdrObj, maFillData );
1222 ConvertFrameStyle( rSdrObj, mnFrameFlags );
1223}
1224
1225void XclImpRectObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1226{
1228 ReadMacro3( rStrm, nMacroSize );
1229}
1230
1231void XclImpRectObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1232{
1234 ReadMacro4( rStrm, nMacroSize );
1235}
1236
1237void XclImpRectObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1238{
1240 ReadName5( rStrm, nNameLen );
1241 ReadMacro5( rStrm, nMacroSize );
1242}
1243
1245{
1247 new SdrRectObj(
1248 *GetDoc().GetDrawLayer(),
1249 rAnchorRect));
1250 ConvertRectStyle( *xSdrObj );
1251 rDffConv.Progress();
1252 return xSdrObj;
1253}
1254
1256 XclImpRectObj( rRoot )
1257{
1258}
1259
1261{
1263 new SdrCircObj(
1264 *GetDoc().GetDrawLayer(),
1265 SdrCircKind::Full,
1266 rAnchorRect));
1267 ConvertRectStyle( *xSdrObj );
1268 rDffConv.Progress();
1269 return xSdrObj;
1270}
1271
1273 XclImpDrawObjBase( rRoot ),
1274 mnQuadrant( EXC_OBJ_ARC_TR )
1275{
1276 SetAreaObj( false ); // arc may be 2-dimensional
1277}
1278
1279void XclImpArcObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1280{
1282 mnQuadrant = rStrm.ReaduInt8();
1283 rStrm.Ignore( 1 );
1284 ReadMacro3( rStrm, nMacroSize );
1285}
1286
1287void XclImpArcObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1288{
1290 mnQuadrant = rStrm.ReaduInt8();
1291 rStrm.Ignore( 1 );
1292 ReadMacro4( rStrm, nMacroSize );
1293}
1294
1295void XclImpArcObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1296{
1298 mnQuadrant = rStrm.ReaduInt8();
1299 rStrm.Ignore( 1 );
1300 ReadName5( rStrm, nNameLen );
1301 ReadMacro5( rStrm, nMacroSize );
1302}
1303
1305{
1306 tools::Rectangle aNewRect = rAnchorRect;
1307 Degree100 nStartAngle;
1308 Degree100 nEndAngle;
1309 switch( mnQuadrant )
1310 {
1311 default:
1312 case EXC_OBJ_ARC_TR:
1313 nStartAngle = 0_deg100;
1314 nEndAngle = 9000_deg100;
1315 aNewRect.AdjustLeft( -(rAnchorRect.GetWidth()) );
1316 aNewRect.AdjustBottom(rAnchorRect.GetHeight() );
1317 break;
1318 case EXC_OBJ_ARC_TL:
1319 nStartAngle = 9000_deg100;
1320 nEndAngle = 18000_deg100;
1321 aNewRect.AdjustRight(rAnchorRect.GetWidth() );
1322 aNewRect.AdjustBottom(rAnchorRect.GetHeight() );
1323 break;
1324 case EXC_OBJ_ARC_BL:
1325 nStartAngle = 18000_deg100;
1326 nEndAngle = 27000_deg100;
1327 aNewRect.AdjustRight(rAnchorRect.GetWidth() );
1328 aNewRect.AdjustTop( -(rAnchorRect.GetHeight()) );
1329 break;
1330 case EXC_OBJ_ARC_BR:
1331 nStartAngle = 27000_deg100;
1332 nEndAngle = 0_deg100;
1333 aNewRect.AdjustLeft( -(rAnchorRect.GetWidth()) );
1334 aNewRect.AdjustTop( -(rAnchorRect.GetHeight()) );
1335 break;
1336 }
1337 SdrCircKind eObjKind = maFillData.IsFilled() ? SdrCircKind::Section : SdrCircKind::Arc;
1339 new SdrCircObj(
1340 *GetDoc().GetDrawLayer(),
1341 eObjKind,
1342 aNewRect,
1343 nStartAngle,
1344 nEndAngle));
1345 ConvertFillStyle( *xSdrObj, maFillData );
1346 ConvertLineStyle( *xSdrObj, maLineData );
1347 rDffConv.Progress();
1348 return xSdrObj;
1349}
1350
1352 XclImpRectObj( rRoot ),
1353 mnPolyFlags( 0 ),
1354 mnPointCount( 0 )
1355{
1356 SetAreaObj( false ); // polygon may be 2-dimensional
1357}
1358
1360{
1361 if( (rStrm.GetNextRecId() == EXC_ID_COORDLIST) && rStrm.StartNextRecord() )
1362 {
1363 OSL_ENSURE( rStrm.GetRecLeft() / 4 == mnPointCount, "XclImpPolygonObj::ReadCoordList - wrong polygon point count" );
1364 while (true)
1365 {
1366 if (rStrm.GetRecLeft() < 4)
1367 break;
1368 sal_uInt16 nX = rStrm.ReaduInt16();
1369 sal_uInt16 nY = rStrm.ReaduInt16();
1370 maCoords.emplace_back( nX, nY );
1371 }
1372 }
1373}
1374
1375void XclImpPolygonObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1376{
1378 mnPolyFlags = rStrm.ReaduInt16();
1379 rStrm.Ignore( 10 );
1380 mnPointCount = rStrm.ReaduInt16();
1381 rStrm.Ignore( 8 );
1382 ReadMacro4( rStrm, nMacroSize );
1384}
1385
1386void XclImpPolygonObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1387{
1389 mnPolyFlags = rStrm.ReaduInt16();
1390 rStrm.Ignore( 10 );
1391 mnPointCount = rStrm.ReaduInt16();
1392 rStrm.Ignore( 8 );
1393 ReadName5( rStrm, nNameLen );
1394 ReadMacro5( rStrm, nMacroSize );
1396}
1397
1398namespace {
1399
1400::basegfx::B2DPoint lclGetPolyPoint( const tools::Rectangle& rAnchorRect, const Point& rPoint )
1401{
1402 return ::basegfx::B2DPoint(
1403 rAnchorRect.Left() + static_cast< sal_Int32 >( ::std::min< double >( rPoint.X(), 16384.0 ) / 16384.0 * rAnchorRect.GetWidth() + 0.5 ),
1404 rAnchorRect.Top() + static_cast< sal_Int32 >( ::std::min< double >( rPoint.Y(), 16384.0 ) / 16384.0 * rAnchorRect.GetHeight() + 0.5 ) );
1405}
1406
1407} // namespace
1408
1410{
1412 if( maCoords.size() >= 2 )
1413 {
1414 // create the polygon
1415 ::basegfx::B2DPolygon aB2DPolygon;
1416 for( const auto& rCoord : maCoords )
1417 aB2DPolygon.append( lclGetPolyPoint( rAnchorRect, rCoord ) );
1418 // close polygon if specified
1419 if( ::get_flag( mnPolyFlags, EXC_OBJ_POLY_CLOSED ) && (maCoords.front() != maCoords.back()) )
1420 aB2DPolygon.append( lclGetPolyPoint( rAnchorRect, maCoords.front() ) );
1421 // create the SdrObject
1422 SdrObjKind eObjKind = maFillData.IsFilled() ? SdrObjKind::PathPoly : SdrObjKind::PathPolyLine;
1423 xSdrObj =
1424 new SdrPathObj(
1425 *GetDoc().GetDrawLayer(),
1426 eObjKind,
1427 ::basegfx::B2DPolyPolygon(aB2DPolygon));
1428 ConvertRectStyle( *xSdrObj );
1429 }
1430 rDffConv.Progress();
1431 return xSdrObj;
1432}
1433
1435{
1436 mxString.reset();
1437 if( maData.mnTextLen > 0 )
1438 {
1439 mxString = std::make_shared<XclImpString>( rStrm.ReadRawByteString( maData.mnTextLen ) );
1440 // skip padding byte for word boundaries
1441 if( rStrm.GetRecPos() & 1 ) rStrm.Ignore( 1 );
1442 }
1443}
1444
1446{
1447 if( mxString )
1448 mxString->ReadObjFormats( rStrm, maData.mnFormatSize );
1449 else
1450 rStrm.Ignore( maData.mnFormatSize );
1451}
1452
1454 XclImpRectObj( rRoot )
1455{
1456}
1457
1458void XclImpTextObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1459{
1462 ReadMacro3( rStrm, nMacroSize );
1465}
1466
1467void XclImpTextObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1468{
1471 ReadMacro4( rStrm, nMacroSize );
1474}
1475
1476void XclImpTextObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1477{
1480 ReadName5( rStrm, nNameLen );
1481 ReadMacro5( rStrm, nMacroSize );
1483 rStrm.Ignore( maTextData.maData.mnLinkSize ); // ignore text link formula
1485}
1486
1488{
1491 *GetDoc().GetDrawLayer()));
1492 xSdrObj->NbcSetSnapRect( rAnchorRect );
1493 OUString aRectType = "rectangle";
1494 xSdrObj->MergeDefaultAttributes( &aRectType );
1495 ConvertRectStyle( *xSdrObj );
1497 xSdrObj->SetMergedItem( makeSdrTextAutoGrowWidthItem( bAutoSize ) );
1498 xSdrObj->SetMergedItem( makeSdrTextAutoGrowHeightItem( bAutoSize ) );
1499 xSdrObj->SetMergedItem( makeSdrTextWordWrapItem( true ) );
1500 rDffConv.Progress();
1501 return xSdrObj;
1502}
1503
1505{
1506 // set text data
1507 if( SdrTextObj* pTextObj = DynCastSdrTextObj( &rSdrObj ) )
1508 {
1509 if( maTextData.mxString )
1510 {
1511 if( maTextData.mxString->IsRich() )
1512 {
1513 if (maTextData.mxString->GetText().getLength() > 1024 && utl::ConfigManager::IsFuzzing())
1514 {
1515 SAL_WARN("sc.filter", "truncating slow long rich text for fuzzing performance");
1516 maTextData.mxString->SetText(maTextData.mxString->GetText().copy(0, 1024));
1517 }
1518
1519 // rich text
1520 std::unique_ptr< EditTextObject > xEditObj(
1522 OutlinerParaObject aOutlineObj(std::move(xEditObj));
1523 aOutlineObj.SetOutlinerMode( OutlinerMode::TextObject );
1524 pTextObj->NbcSetOutlinerParaObject( std::move(aOutlineObj) );
1525 }
1526 else
1527 {
1528 // plain text
1529 pTextObj->NbcSetText( maTextData.mxString->GetText() );
1530 }
1531
1532 /* #i96858# Do not apply any formatting if there is no text.
1533 SdrObjCustomShape::SetVerticalWriting (initiated from
1534 SetMergedItem) calls SdrTextObj::ForceOutlinerParaObject which
1535 ensures that we can erroneously write a ClientTextbox record
1536 (with no content) while exporting to XLS, which can cause a
1537 corrupted exported document. */
1538
1539 SvxAdjust eHorAlign = SvxAdjust::Left;
1541
1542 // orientation (this is only a fake, drawing does not support real text orientation)
1543 namespace csst = ::com::sun::star::text;
1544 csst::WritingMode eWriteMode = csst::WritingMode_LR_TB;
1545 switch( maTextData.maData.mnOrient )
1546 {
1547 default:
1549 {
1550 eWriteMode = csst::WritingMode_LR_TB;
1551 switch( maTextData.maData.GetHorAlign() )
1552 {
1553 case EXC_OBJ_HOR_LEFT: eHorAlign = SvxAdjust::Left; break;
1554 case EXC_OBJ_HOR_CENTER: eHorAlign = SvxAdjust::Center; break;
1555 case EXC_OBJ_HOR_RIGHT: eHorAlign = SvxAdjust::Right; break;
1556 case EXC_OBJ_HOR_JUSTIFY: eHorAlign = SvxAdjust::Block; break;
1557 }
1558 switch( maTextData.maData.GetVerAlign() )
1559 {
1560 case EXC_OBJ_VER_TOP: eVerAlign = SDRTEXTVERTADJUST_TOP; break;
1561 case EXC_OBJ_VER_CENTER: eVerAlign = SDRTEXTVERTADJUST_CENTER; break;
1562 case EXC_OBJ_VER_BOTTOM: eVerAlign = SDRTEXTVERTADJUST_BOTTOM; break;
1563 case EXC_OBJ_VER_JUSTIFY: eVerAlign = SDRTEXTVERTADJUST_BLOCK; break;
1564 }
1565 }
1566 break;
1567
1569 {
1570 if( SdrObjCustomShape* pObjCustomShape = dynamic_cast< SdrObjCustomShape* >( &rSdrObj ) )
1571 {
1572 css::beans::PropertyValue aTextRotateAngle;
1573 aTextRotateAngle.Name = "TextRotateAngle";
1574 aTextRotateAngle.Value <<= 180.0;
1575 SdrCustomShapeGeometryItem aGeometryItem(pObjCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ));
1576 aGeometryItem.SetPropertyValue( aTextRotateAngle );
1577 pObjCustomShape->SetMergedItem( aGeometryItem );
1578 }
1579 eWriteMode = csst::WritingMode_TB_RL;
1580 switch( maTextData.maData.GetHorAlign() )
1581 {
1582 case EXC_OBJ_HOR_LEFT: eVerAlign = SDRTEXTVERTADJUST_TOP; break;
1583 case EXC_OBJ_HOR_CENTER: eVerAlign = SDRTEXTVERTADJUST_CENTER; break;
1584 case EXC_OBJ_HOR_RIGHT: eVerAlign = SDRTEXTVERTADJUST_BOTTOM; break;
1585 case EXC_OBJ_HOR_JUSTIFY: eVerAlign = SDRTEXTVERTADJUST_BLOCK; break;
1586 }
1587 MSO_Anchor eTextAnchor = static_cast<MSO_Anchor>(rDffConv.GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop ));
1588 switch( eTextAnchor )
1589 {
1593 {
1594 eHorAlign = SvxAdjust::Center;
1595 }
1596 break;
1597
1598 default:
1599 {
1600 switch( maTextData.maData.GetVerAlign() )
1601 {
1602 case EXC_OBJ_VER_TOP: eHorAlign = SvxAdjust::Right; break;
1603 case EXC_OBJ_VER_CENTER: eHorAlign = SvxAdjust::Center; break;
1604 case EXC_OBJ_VER_BOTTOM: eHorAlign = SvxAdjust::Left; break;
1605 case EXC_OBJ_VER_JUSTIFY: eHorAlign = SvxAdjust::Block; break;
1606 }
1607 }
1608 }
1609 }
1610 break;
1611
1613 {
1614 // sj: STACKED is not supported, maybe it can be optimized here a bit
1615 [[fallthrough]];
1616 }
1618 {
1619 eWriteMode = csst::WritingMode_TB_RL;
1620 switch( maTextData.maData.GetHorAlign() )
1621 {
1622 case EXC_OBJ_HOR_LEFT: eVerAlign = SDRTEXTVERTADJUST_BOTTOM; break;
1623 case EXC_OBJ_HOR_CENTER: eVerAlign = SDRTEXTVERTADJUST_CENTER; break;
1624 case EXC_OBJ_HOR_RIGHT: eVerAlign = SDRTEXTVERTADJUST_TOP; break;
1625 case EXC_OBJ_HOR_JUSTIFY: eVerAlign = SDRTEXTVERTADJUST_BLOCK; break;
1626 }
1627 MSO_Anchor eTextAnchor = static_cast<MSO_Anchor>(rDffConv.GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop ));
1628 switch ( eTextAnchor )
1629 {
1633 {
1634 eHorAlign = SvxAdjust::Center;
1635 }
1636 break;
1637
1638 default:
1639 {
1640 switch( maTextData.maData.GetVerAlign() )
1641 {
1642 case EXC_OBJ_VER_TOP: eHorAlign = SvxAdjust::Left; break;
1643 case EXC_OBJ_VER_CENTER: eHorAlign = SvxAdjust::Center; break;
1644 case EXC_OBJ_VER_BOTTOM: eHorAlign = SvxAdjust::Right; break;
1645 case EXC_OBJ_VER_JUSTIFY: eHorAlign = SvxAdjust::Block; break;
1646 }
1647 }
1648 }
1649 }
1650 break;
1651 }
1652 rSdrObj.SetMergedItem( SvxAdjustItem( eHorAlign, EE_PARA_JUST ) );
1653 rSdrObj.SetMergedItem( SdrTextVertAdjustItem( eVerAlign ) );
1654 rSdrObj.SetMergedItem( SvxWritingModeItem( eWriteMode, SDRATTR_TEXTDIRECTION ) );
1655 }
1656 }
1657 // base class processing
1658 XclImpRectObj::DoPreProcessSdrObj( rDffConv, rSdrObj );
1659}
1660
1661XclImpChartObj::XclImpChartObj( const XclImpRoot& rRoot, bool bOwnTab ) :
1662 XclImpRectObj( rRoot ),
1663 mbOwnTab( bOwnTab )
1664{
1665 SetSimpleMacro( false );
1666 SetCustomDffObj( true );
1667}
1668
1670{
1671 /* If chart is read from a chartsheet (mbOwnTab == true), the BOF record
1672 has already been read. If chart is embedded as object, the next record
1673 has to be the BOF record. */
1674 if( mbOwnTab )
1675 {
1676 /* #i109800# The input stream may point somewhere inside the chart
1677 substream and not exactly to the leading BOF record. To read this
1678 record correctly in the following, the stream has to rewind it, so
1679 that the next call to StartNextRecord() will find it correctly. */
1680 if( rStrm.GetRecId() != EXC_ID5_BOF )
1681 rStrm.RewindRecord();
1682 }
1683 else
1684 {
1685 if( (rStrm.GetNextRecId() == EXC_ID5_BOF) && rStrm.StartNextRecord() )
1686 {
1687 sal_uInt16 nBofType;
1688 rStrm.Seek( 2 );
1689 nBofType = rStrm.ReaduInt16();
1690 SAL_WARN_IF( nBofType != EXC_BOF_CHART, "sc.filter", "XclImpChartObj::ReadChartSubStream - no chart BOF record" );
1691 }
1692 else
1693 {
1694 SAL_INFO("sc.filter", "XclImpChartObj::ReadChartSubStream - missing chart substream");
1695 return;
1696 }
1697 }
1698
1699 // read chart, even if BOF record contains wrong substream identifier
1700 mxChart = std::make_shared<XclImpChart>( GetRoot(), mbOwnTab );
1701 mxChart->ReadChartSubStream( rStrm );
1702 if( mbOwnTab )
1704}
1705
1706void XclImpChartObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1707{
1708 // read OBJ record and the following chart substream
1710 rStrm.Ignore( 18 );
1711 ReadMacro3( rStrm, nMacroSize );
1712 // set frame format from OBJ record, it is used if chart itself is transparent
1713 if( mxChart )
1714 mxChart->UpdateObjFrame( maLineData, maFillData );
1715}
1716
1717void XclImpChartObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
1718{
1719 // read OBJ record and the following chart substream
1721 rStrm.Ignore( 18 );
1722 ReadMacro4( rStrm, nMacroSize );
1723 // set frame format from OBJ record, it is used if chart itself is transparent
1724 if( mxChart )
1725 mxChart->UpdateObjFrame( maLineData, maFillData );
1726}
1727
1728void XclImpChartObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
1729{
1730 // read OBJ record and the following chart substream
1732 rStrm.Ignore( 18 );
1733 ReadName5( rStrm, nNameLen );
1734 ReadMacro5( rStrm, nMacroSize );
1736 // set frame format from OBJ record, it is used if chart itself is transparent
1737 if( mxChart )
1738 mxChart->UpdateObjFrame( maLineData, maFillData );
1739}
1740
1741void XclImpChartObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 /*nSubRecSize*/ )
1742{
1743 // read the following chart substream
1744 if( nSubRecId == EXC_ID_OBJEND )
1745 {
1746 // enable CONTINUE handling for the entire chart substream
1747 rStrm.ResetRecord( true );
1749 /* disable CONTINUE handling again to be able to read
1750 following CONTINUE records as MSODRAWING records. */
1751 rStrm.ResetRecord( false );
1752 }
1753}
1754
1756{
1757 return mxChart ? mxChart->GetProgressSize() : 1;
1758}
1759
1761{
1763 SfxObjectShell* pDocShell = GetDocShell();
1764 if( rDffConv.SupportsOleObjects() && SvtModuleOptions().IsChart() && pDocShell && mxChart && !mxChart->IsPivotChart() )
1765 {
1766 // create embedded chart object
1767 OUString aEmbObjName;
1768 OUString sBaseURL(GetRoot().GetMedium().GetBaseURL());
1769 Reference< XEmbeddedObject > xEmbObj = pDocShell->GetEmbeddedObjectContainer().
1770 CreateEmbeddedObject( SvGlobalName( SO3_SCH_CLASSID ).GetByteSequence(), aEmbObjName, &sBaseURL );
1771
1772 if (!xEmbObj)
1773 return xSdrObj;
1774
1775 /* Set the size to the embedded object, this prevents that font sizes
1776 of text objects are changed in the chart when the object is
1777 inserted into the draw page. */
1778 sal_Int64 nAspect = css::embed::Aspects::MSOLE_CONTENT;
1779 MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xEmbObj->getMapUnit( nAspect ) );
1780 Size aSize( OutputDevice::LogicToLogic( rAnchorRect.GetSize(), MapMode( MapUnit::Map100thMM ), MapMode( aUnit ) ) );
1781 css::awt::Size aAwtSize( aSize.Width(), aSize.Height() );
1782 xEmbObj->setVisualAreaSize( nAspect, aAwtSize );
1783
1784 // #i121334# This call will change the chart's default background fill from white to transparent.
1785 // Add here again if this is wanted (see task description for details)
1786 // ChartHelper::AdaptDefaultsForChart( xEmbObj );
1787
1788 // create the container OLE object
1789 xSdrObj =
1790 new SdrOle2Obj(
1791 *GetDoc().GetDrawLayer(),
1792 svt::EmbeddedObjectRef(xEmbObj, nAspect),
1793 aEmbObjName,
1794 rAnchorRect);
1795 }
1796
1797 return xSdrObj;
1798}
1799
1801{
1802 const SdrOle2Obj* pSdrOleObj = dynamic_cast< const SdrOle2Obj* >( &rSdrObj );
1803 if( !(mxChart && pSdrOleObj) )
1804 return;
1805
1806 const Reference< XEmbeddedObject >& xEmbObj = pSdrOleObj->GetObjRef();
1807 if( xEmbObj.is() && ::svt::EmbeddedObjectRef::TryRunningState( xEmbObj ) ) try
1808 {
1809 Reference< XEmbedPersist > xPersist( xEmbObj, UNO_QUERY_THROW );
1810 Reference< XModel > xModel( xEmbObj->getComponent(), UNO_QUERY_THROW );
1811 mxChart->Convert( xModel, rDffConv, xPersist->getEntryName(), rSdrObj.GetLogicRect() );
1812 }
1813 catch( const Exception& )
1814 {
1815 }
1816}
1817
1819{
1820 /* #i44077# Calculate and store DFF anchor for sheet charts.
1821 Needed to get used area if this chart is inserted as OLE object. */
1822 OSL_ENSURE( mbOwnTab, "XclImpChartObj::FinalizeTabChart - not allowed for embedded chart objects" );
1823
1824 // set uninitialized page to landscape
1825 if( !GetPageSettings().GetPageData().mbValid )
1827
1828 // calculate size of the chart object
1829 const XclPageData& rPageData = GetPageSettings().GetPageData();
1830 Size aPaperSize = rPageData.GetScPaperSize();
1831
1832 tools::Long nWidth = XclTools::GetHmmFromTwips( aPaperSize.Width() );
1833 tools::Long nHeight = XclTools::GetHmmFromTwips( aPaperSize.Height() );
1834
1835 // subtract page margins, give some more extra space
1836 nWidth -= o3tl::saturating_add(XclTools::GetHmmFromInch(rPageData.mfLeftMargin + rPageData.mfRightMargin), static_cast<sal_Int32>(2000));
1837 nHeight -= o3tl::saturating_add(XclTools::GetHmmFromInch(rPageData.mfTopMargin + rPageData.mfBottomMargin), static_cast<sal_Int32>(1000));
1838
1839 // print column/row headers?
1840 if( rPageData.mbPrintHeadings )
1841 {
1842 nWidth -= 2000;
1843 nHeight -= 1000;
1844 }
1845
1846 // create the object anchor
1847 XclObjAnchor aAnchor;
1848 aAnchor.SetRect( GetRoot(), GetCurrScTab(), tools::Rectangle( 1000, 500, nWidth, nHeight ), MapUnit::Map100thMM );
1849 SetAnchor( aAnchor );
1850}
1851
1853 XclImpTextObj( rRoot ),
1854 maScPos( ScAddress::INITIALIZE_INVALID ),
1855 mnNoteFlags( 0 )
1856{
1857 SetSimpleMacro( false );
1858 // caption object will be created manually
1859 SetInsertSdrObj( false );
1860}
1861
1862void XclImpNoteObj::SetNoteData( const ScAddress& rScPos, sal_uInt16 nNoteFlags )
1863{
1864 maScPos = rScPos;
1865 mnNoteFlags = nNoteFlags;
1866}
1867
1869{
1870 // create formatted text
1871 XclImpTextObj::DoPreProcessSdrObj( rDffConv, rSdrObj );
1872 OutlinerParaObject* pOutlinerObj = rSdrObj.GetOutlinerParaObject();
1873 if( maScPos.IsValid() && pOutlinerObj )
1874 {
1875 // create cell note with all data from drawing object
1877 GetDoc(), maScPos,
1878 rSdrObj.GetMergedItemSet().CloneAsValue(), // new object on heap expected
1879 OUString(), *pOutlinerObj,
1880 rSdrObj.GetLogicRect(),
1882 }
1883}
1884
1886 mrRoot( rRoot ),
1887 meBindMode( eBindMode )
1888{
1889}
1890
1892{
1893}
1894
1896 const Reference< XShape >& rxShape, const tools::Rectangle& rAnchorRect ) const
1897{
1898 mxShape = rxShape;
1900 if( xSdrObj )
1901 {
1902 xSdrObj->NbcSetSnapRect( rAnchorRect );
1903 // #i30543# insert into control layer
1904 xSdrObj->NbcSetLayer( SC_LAYER_CONTROLS );
1905 }
1906 return xSdrObj;
1907}
1908
1910{
1911
1912 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( mxShape );
1913 if( !xCtrlModel.is() )
1914 return;
1915
1916 // sheet links
1917 SfxObjectShell* pDocShell = mrRoot.GetDocShell();
1918 if(!pDocShell)
1919 return;
1920
1921 Reference< XMultiServiceFactory > xFactory( pDocShell->GetModel(), UNO_QUERY );
1922 if( !xFactory.is() )
1923 return;
1924
1925 // cell link
1926 if( mxCellLink ) try
1927 {
1928 Reference< XBindableValue > xBindable( xCtrlModel, UNO_QUERY_THROW );
1929
1930 // create argument sequence for createInstanceWithArguments()
1931 CellAddress aApiAddress;
1933
1934 NamedValue aValue;
1935 aValue.Name = SC_UNONAME_BOUNDCELL;
1936 aValue.Value <<= aApiAddress;
1937
1938 Sequence< Any > aArgs{ Any(aValue) };
1939
1940 // create the CellValueBinding instance and set at the control model
1941 OUString aServiceName;
1942 switch( meBindMode )
1943 {
1944 case EXC_CTRL_BINDCONTENT: aServiceName = SC_SERVICENAME_VALBIND; break;
1945 case EXC_CTRL_BINDPOSITION: aServiceName = SC_SERVICENAME_LISTCELLBIND; break;
1946 }
1947 Reference< XValueBinding > xBinding(
1948 xFactory->createInstanceWithArguments( aServiceName, aArgs ), UNO_QUERY_THROW );
1949 xBindable->setValueBinding( xBinding );
1950 }
1951 catch( const Exception& )
1952 {
1953 }
1954
1955 // source range
1956 if( !mxSrcRange )
1957 return;
1958
1959 try
1960 {
1961 Reference< XListEntrySink > xEntrySink( xCtrlModel, UNO_QUERY_THROW );
1962
1963 // create argument sequence for createInstanceWithArguments()
1964 CellRangeAddress aApiRange;
1966
1967 NamedValue aValue;
1968 aValue.Name = SC_UNONAME_CELLRANGE;
1969 aValue.Value <<= aApiRange;
1970
1971 Sequence< Any > aArgs{ Any(aValue) };
1972
1973 // create the EntrySource instance and set at the control model
1974 Reference< XListEntrySource > xEntrySource( xFactory->createInstanceWithArguments(
1975 SC_SERVICENAME_LISTSOURCE, aArgs ), UNO_QUERY_THROW );
1976 xEntrySink->setListEntrySource( xEntrySource );
1977 }
1978 catch( const Exception& )
1979 {
1980 }
1981}
1982
1984{
1985 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( mxShape );
1986 if( !xCtrlModel.is() )
1987 return;
1988
1990
1991 ScfPropertySet aPropSet( xCtrlModel );
1992
1993 // #i51348# set object name at control model
1994 aPropSet.SetStringProperty( "Name", rDrawObj.GetObjName() );
1995
1996 // control visible and printable?
1997 aPropSet.SetBoolProperty( "EnableVisible", rDrawObj.IsVisible() );
1998 aPropSet.SetBoolProperty( "Printable", rDrawObj.IsPrintable() );
1999
2000 // virtual call for type specific processing
2001 DoProcessControl( aPropSet );
2002}
2003
2005{
2006 ScRangeList aScRanges;
2007 ReadRangeList( aScRanges, rStrm, bWithBoundSize );
2008 // Use first cell of first range
2009 if ( !aScRanges.empty() )
2010 {
2011 const ScRange & rScRange = aScRanges.front();
2012 mxCellLink = std::make_shared<ScAddress>( rScRange.aStart );
2013 }
2014}
2015
2017{
2018 ScRangeList aScRanges;
2019 ReadRangeList( aScRanges, rStrm, bWithBoundSize );
2020 // Use first range
2021 if ( !aScRanges.empty() )
2022 {
2023 const ScRange & rScRange = aScRanges.front();
2024 mxSrcRange = std::make_shared<ScRange>( rScRange );
2025 }
2026}
2027
2029{
2030}
2031
2033{
2034 XclTokenArray aXclTokArr;
2035 sal_uInt16 nSize = XclTokenArray::ReadSize(rStrm);
2036 rStrm.Ignore( 4 );
2037 aXclTokArr.ReadArray(nSize, rStrm);
2039}
2040
2041void XclImpControlHelper::ReadRangeList( ScRangeList& rScRanges, XclImpStream& rStrm, bool bWithBoundSize )
2042{
2043 if( bWithBoundSize )
2044 {
2045 sal_uInt16 nSize;
2046 nSize = rStrm.ReaduInt16();
2047 if( nSize > 0 )
2048 {
2049 rStrm.PushPosition();
2050 ReadRangeList( rScRanges, rStrm );
2051 rStrm.PopPosition();
2052 rStrm.Ignore( nSize );
2053 }
2054 }
2055 else
2056 {
2057 ReadRangeList( rScRanges, rStrm );
2058 }
2059}
2060
2062 XclImpTextObj( rRoot ),
2064{
2065 SetSimpleMacro( false );
2066 SetCustomDffObj( true );
2067}
2068
2069namespace {
2070
2071void lclExtractColor( sal_uInt8& rnColorIdx, const DffPropSet& rDffPropSet, sal_uInt32 nPropId )
2072{
2073 if( rDffPropSet.IsProperty( nPropId ) )
2074 {
2075 sal_uInt32 nColor = rDffPropSet.GetPropertyValue( nPropId, 0 );
2076 if( (nColor & 0xFF000000) == 0x08000000 )
2077 rnColorIdx = ::extract_value< sal_uInt8 >( nColor, 0, 8 );
2078 }
2079}
2080
2081} // namespace
2082
2084{
2086 lclExtractColor( maFillData.mnBackColorIdx, rDffPropSet, DFF_Prop_fillBackColor );
2087 lclExtractColor( maFillData.mnPattColorIdx, rDffPropSet, DFF_Prop_fillColor );
2089
2091 lclExtractColor( maLineData.mnColorIdx, rDffPropSet, DFF_Prop_lineColor );
2093}
2094
2095void XclImpControlHelper::SetStringProperty(const OUString& sName, const OUString& sVal)
2096{
2097 Reference<XControlModel> xCtrlModel = XclControlHelper::GetControlModel(mxShape);
2098 if (!xCtrlModel.is())
2099 return;
2100
2101 ScfPropertySet aProps(xCtrlModel);
2102 aProps.SetStringProperty(sName, sVal);
2103}
2104
2105bool XclImpTbxObjBase::FillMacroDescriptor( ScriptEventDescriptor& rDescriptor ) const
2106{
2108}
2109
2111{
2112 if( maTextData.mxString )
2113 {
2114 const XclFormatRunVec& rFormatRuns = maTextData.mxString->GetFormats();
2115 if( rFormatRuns.empty() )
2117 else
2118 GetFontBuffer().WriteFontProperties( rPropSet, EXC_FONTPROPSET_CONTROL, rFormatRuns.front().mnFontIdx );
2119 }
2120}
2121
2123{
2124 if( maTextData.mxString )
2125 {
2126 OUString aLabel = maTextData.mxString->GetText();
2127 if( maTextData.maData.mnShortcut > 0 )
2128 {
2129 sal_Int32 nPos = aLabel.indexOf( static_cast< sal_Unicode >( maTextData.maData.mnShortcut ) );
2130 if( nPos != -1 )
2131 aLabel = aLabel.replaceAt( nPos, 0, u"~" );
2132 }
2133 rPropSet.SetStringProperty( "Label", aLabel );
2134
2135 //Excel Alt text <==> Aoo description
2136 //For TBX control, if user does not operate alt text, alt text will be set label text as default value in Excel.
2137 //In this case, DFF_Prop_wzDescription will not be set in excel file.
2138 //So In the end of SvxMSDffManager::ImportShape, description will not be set. But actually in excel,
2139 //the alt text is the label value. So here set description as label text first which is called before ImportShape.
2140 Reference< css::beans::XPropertySet > xPropset( mxShape, UNO_QUERY );
2141 try{
2142 if(xPropset.is())
2143 xPropset->setPropertyValue( "Description", Any(aLabel) );
2144 }catch( ... )
2145 {
2146 SAL_WARN("sc.filter", "Can't set a default text for TBX Control ");
2147 }
2148 }
2149 ConvertFont( rPropSet );
2150}
2151
2153{
2154 rtl::Reference<SdrObject> xSdrObj( rDffConv.CreateSdrObject( *this, rAnchorRect ) );
2155 rDffConv.Progress();
2156 return xSdrObj;
2157}
2158
2160{
2161 // do not call DoPreProcessSdrObj() from base class (to skip text processing)
2162 ProcessControl( *this );
2163}
2164
2166 XclImpTbxObjBase( rRoot )
2167{
2168}
2169
2171{
2172 // label and text formatting
2173 ConvertLabel( rPropSet );
2174
2175 /* Horizontal text alignment. For unknown reason, the property type is a
2176 simple sal_Int16 and not a com.sun.star.style.HorizontalAlignment. */
2177 sal_Int16 nHorAlign = 1;
2178 switch( maTextData.maData.GetHorAlign() )
2179 {
2180 case EXC_OBJ_HOR_LEFT: nHorAlign = 0; break;
2181 case EXC_OBJ_HOR_CENTER: nHorAlign = 1; break;
2182 case EXC_OBJ_HOR_RIGHT: nHorAlign = 2; break;
2183 }
2184 rPropSet.SetProperty( "Align", nHorAlign );
2185
2186 // vertical text alignment
2187 namespace csss = ::com::sun::star::style;
2188 csss::VerticalAlignment eVerAlign = csss::VerticalAlignment_MIDDLE;
2189 switch( maTextData.maData.GetVerAlign() )
2190 {
2191 case EXC_OBJ_VER_TOP: eVerAlign = csss::VerticalAlignment_TOP; break;
2192 case EXC_OBJ_VER_CENTER: eVerAlign = csss::VerticalAlignment_MIDDLE; break;
2193 case EXC_OBJ_VER_BOTTOM: eVerAlign = csss::VerticalAlignment_BOTTOM; break;
2194 }
2195 rPropSet.SetProperty( "VerticalAlign", eVerAlign );
2196
2197 // always wrap text automatically
2198 rPropSet.SetBoolProperty( "MultiLine", true );
2199
2200 // default button
2202 rPropSet.SetBoolProperty( "DefaultButton", bDefButton );
2203
2204 // button type (flags cannot be combined in OOo)
2205 namespace cssa = ::com::sun::star::awt;
2206 cssa::PushButtonType eButtonType = cssa::PushButtonType_STANDARD;
2208 eButtonType = cssa::PushButtonType_OK;
2210 eButtonType = cssa::PushButtonType_CANCEL;
2212 eButtonType = cssa::PushButtonType_HELP;
2213 // property type is short, not enum
2214 rPropSet.SetProperty( "PushButtonType", sal_Int16( eButtonType ) );
2215}
2216
2218{
2219 return "com.sun.star.form.component.CommandButton";
2220}
2221
2223{
2224 return EXC_TBX_EVENT_ACTION;
2225}
2226
2228 XclImpTbxObjBase( rRoot ),
2229 mnState( EXC_OBJ_CHECKBOX_UNCHECKED ),
2230 mnCheckBoxFlags( 0 )
2231{
2232}
2233
2234void XclImpCheckBoxObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2235{
2237 rStrm.Ignore( 10 );
2238 maTextData.maData.mnFlags = rStrm.ReaduInt16();
2239 rStrm.Ignore( 20 );
2240 ReadName5( rStrm, nNameLen );
2241 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2242 ReadCellLinkFormula( rStrm, true );
2243 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2245 mnState = rStrm.ReaduInt16();
2246 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2247 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16();
2248 mnCheckBoxFlags = rStrm.ReaduInt16();
2249}
2250
2251void XclImpCheckBoxObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2252{
2253 switch( nSubRecId )
2254 {
2255 case EXC_ID_OBJCBLS:
2256 // do not read EXC_ID_OBJCBLSDATA, not written by OOo Excel export
2257 mnState = rStrm.ReaduInt16();
2258 rStrm.Ignore( 4 );
2259 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2260 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16();
2261 mnCheckBoxFlags = rStrm.ReaduInt16();
2262 break;
2263 case EXC_ID_OBJCBLSFMLA:
2264 ReadCellLinkFormula( rStrm, false );
2265 break;
2266 default:
2267 XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2268 }
2269}
2270
2272{
2273 // label and text formatting
2274 ConvertLabel( rPropSet );
2275
2276 // state
2277 bool bSupportsTristate = GetObjType() == EXC_OBJTYPE_CHECKBOX;
2278 sal_Int16 nApiState = 0;
2279 switch( mnState )
2280 {
2281 case EXC_OBJ_CHECKBOX_UNCHECKED: nApiState = 0; break;
2282 case EXC_OBJ_CHECKBOX_CHECKED: nApiState = 1; break;
2283 case EXC_OBJ_CHECKBOX_TRISTATE: nApiState = bSupportsTristate ? 2 : 1; break;
2284 }
2285 if( bSupportsTristate )
2286 rPropSet.SetBoolProperty( "TriState", nApiState == 2 );
2287 rPropSet.SetProperty( "DefaultState", nApiState );
2288
2289 // box style
2290 namespace AwtVisualEffect = ::com::sun::star::awt::VisualEffect;
2291 sal_Int16 nEffect = ::get_flagvalue( mnCheckBoxFlags, EXC_OBJ_CHECKBOX_FLAT, AwtVisualEffect::FLAT, AwtVisualEffect::LOOK3D );
2292 rPropSet.SetProperty( "VisualEffect", nEffect );
2293
2294 // do not wrap text automatically
2295 rPropSet.SetBoolProperty( "MultiLine", false );
2296
2297 // #i40279# always centered vertically
2298 namespace csss = ::com::sun::star::style;
2299 rPropSet.SetProperty( "VerticalAlign", csss::VerticalAlignment_MIDDLE );
2300
2301 // background color
2302 if( maFillData.IsFilled() )
2303 {
2304 sal_Int32 nColor = static_cast< sal_Int32 >( GetSolidFillColor( maFillData ) );
2305 rPropSet.SetProperty( "BackgroundColor", nColor );
2306 }
2307}
2308
2310{
2311 return "com.sun.star.form.component.CheckBox";
2312}
2313
2315{
2316 return EXC_TBX_EVENT_ACTION;
2317}
2318
2320 XclImpCheckBoxObj( rRoot ),
2321 mnNextInGroup( 0 ),
2322 mnFirstInGroup( 1 )
2323{
2324}
2325
2326void XclImpOptionButtonObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2327{
2329 rStrm.Ignore( 10 );
2330 maTextData.maData.mnFlags = rStrm.ReaduInt16();
2331 rStrm.Ignore( 32 );
2332 ReadName5( rStrm, nNameLen );
2333 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2334 ReadCellLinkFormula( rStrm, true );
2335 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2337 mnState = rStrm.ReaduInt16();
2338 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2339 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16();
2340 mnCheckBoxFlags = rStrm.ReaduInt16();
2341 mnNextInGroup = rStrm.ReaduInt16();
2342 mnFirstInGroup = rStrm.ReaduInt16();
2343}
2344
2345void XclImpOptionButtonObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2346{
2347 switch( nSubRecId )
2348 {
2349 case EXC_ID_OBJRBODATA:
2350 mnNextInGroup = rStrm.ReaduInt16();
2351 mnFirstInGroup = rStrm.ReaduInt16();
2352 break;
2353 default:
2354 XclImpCheckBoxObj::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2355 }
2356}
2357
2359{
2361 // TODO: grouping
2363 if ( pTbxObj && pTbxObj->mnFirstInGroup )
2364 {
2365 // Group has terminated
2366 // traverse each RadioButton in group and
2367 // a) apply the groupname
2368 // b) propagate the linked cell from the lead radiobutton
2369 // c) apply the correct Ref value
2370 XclImpOptionButtonObj* pLeader = pTbxObj;
2371
2372 sal_Int32 nRefVal = 1;
2373 do
2374 {
2375
2376 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( pTbxObj->mxShape );
2377 if ( xCtrlModel.is() )
2378 {
2379 ScfPropertySet aProps( xCtrlModel );
2380 OUString sGroupName = OUString::number( pLeader->GetDffShapeId() );
2381
2382 aProps.SetStringProperty( "GroupName", sGroupName );
2383 aProps.SetStringProperty( "RefValue", OUString::number( nRefVal++ ) );
2384 if ( pLeader->HasCellLink() && !pTbxObj->HasCellLink() )
2385 {
2386 // propagate cell link info
2387 pTbxObj->mxCellLink = std::make_shared<ScAddress>( *pLeader->mxCellLink );
2388 pTbxObj->ApplySheetLinkProps();
2389 }
2390 pTbxObj = dynamic_cast< XclImpOptionButtonObj* >( GetObjectManager().GetSheetDrawing( GetTab() ).FindDrawObj( pTbxObj->mnNextInGroup ).get() );
2391 }
2392 else
2393 pTbxObj = nullptr;
2394 } while ( pTbxObj && ( pTbxObj->mnFirstInGroup != 1 ) );
2395 }
2396 else
2397 {
2398 // not the leader? try and find it
2399 }
2400}
2401
2403{
2404 return "com.sun.star.form.component.RadioButton";
2405}
2406
2408{
2409 return EXC_TBX_EVENT_ACTION;
2410}
2411
2413{
2414 return mnNextInGroup;
2415}
2416
2418 XclImpTbxObjBase( rRoot )
2419{
2420}
2421
2423{
2424 // label and text formatting
2425 ConvertLabel( rPropSet );
2426
2427 // text alignment (always top/left aligned)
2428 rPropSet.SetProperty( "Align", sal_Int16( 0 ) );
2429 namespace csss = ::com::sun::star::style;
2430 rPropSet.SetProperty( "VerticalAlign", csss::VerticalAlignment_TOP );
2431
2432 // always wrap text automatically
2433 rPropSet.SetBoolProperty( "MultiLine", true );
2434}
2435
2437{
2438 return "com.sun.star.form.component.FixedText";
2439}
2440
2442{
2443 return EXC_TBX_EVENT_MOUSE;
2444}
2445
2447 XclImpTbxObjBase( rRoot ),
2448 mnGroupBoxFlags( 0 )
2449{
2450}
2451
2452void XclImpGroupBoxObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2453{
2455 rStrm.Ignore( 10 );
2456 maTextData.maData.mnFlags = rStrm.ReaduInt16();
2457 rStrm.Ignore( 26 );
2458 ReadName5( rStrm, nNameLen );
2459 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2460 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2462 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2463 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16( );
2464 mnGroupBoxFlags = rStrm.ReaduInt16();
2465}
2466
2467void XclImpGroupBoxObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2468{
2469 switch( nSubRecId )
2470 {
2471 case EXC_ID_OBJGBODATA:
2472 maTextData.maData.mnShortcut = rStrm.ReaduInt16();
2473 maTextData.maData.mnShortcutEA = rStrm.ReaduInt16();
2474 mnGroupBoxFlags = rStrm.ReaduInt16();
2475 break;
2476 default:
2477 XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2478 }
2479}
2480
2482{
2483 // label and text formatting
2484 ConvertLabel( rPropSet );
2485}
2486
2488{
2489 return "com.sun.star.form.component.GroupBox";
2490}
2491
2493{
2494 return EXC_TBX_EVENT_MOUSE;
2495}
2496
2498 XclImpTbxObjBase( rRoot )
2499{
2500}
2501
2503{
2504 // label and text formatting
2505 ConvertLabel( rPropSet );
2506}
2507
2509{
2510 // dialog frame faked by a groupbox
2511 return "com.sun.star.form.component.GroupBox";
2512}
2513
2515{
2516 return EXC_TBX_EVENT_MOUSE;
2517}
2518
2520 XclImpTbxObjBase( rRoot ),
2521 mnContentType( EXC_OBJ_EDIT_TEXT ),
2522 mnMultiLine( 0 ),
2523 mnScrollBar( 0 ),
2524 mnListBoxObjId( 0 )
2525{
2526}
2527
2529{
2531}
2532
2533void XclImpEditObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2534{
2536 rStrm.Ignore( 10 );
2537 maTextData.maData.mnFlags = rStrm.ReaduInt16();
2538 rStrm.Ignore( 14 );
2539 ReadName5( rStrm, nNameLen );
2540 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2541 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2543 mnContentType = rStrm.ReaduInt16();
2544 mnMultiLine = rStrm.ReaduInt16();
2545 mnScrollBar = rStrm.ReaduInt16();
2546 mnListBoxObjId = rStrm.ReaduInt16();
2547}
2548
2549void XclImpEditObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2550{
2551 switch( nSubRecId )
2552 {
2553 case EXC_ID_OBJEDODATA:
2554 mnContentType = rStrm.ReaduInt16();
2555 mnMultiLine = rStrm.ReaduInt16();
2556 mnScrollBar = rStrm.ReaduInt16();
2557 mnListBoxObjId = rStrm.ReaduInt16();
2558 break;
2559 default:
2560 XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2561 }
2562}
2563
2565{
2566 if( maTextData.mxString )
2567 {
2568 OUString aText = maTextData.mxString->GetText();
2569 if( IsNumeric() )
2570 {
2571 // TODO: OUString::toDouble() does not handle local decimal separator
2572 rPropSet.SetProperty( "DefaultValue", aText.toDouble() );
2573 rPropSet.SetBoolProperty( "Spin", mnScrollBar != 0 );
2574 }
2575 else
2576 {
2577 rPropSet.SetProperty( "DefaultText", aText );
2578 rPropSet.SetBoolProperty( "MultiLine", mnMultiLine != 0 );
2579 rPropSet.SetBoolProperty( "VScroll", mnScrollBar != 0 );
2580 }
2581 }
2582 ConvertFont( rPropSet );
2583}
2584
2586{
2587 return IsNumeric() ?
2588 OUString( "com.sun.star.form.component.NumericField" ) :
2589 OUString( "com.sun.star.form.component.TextField" );
2590}
2591
2593{
2594 return EXC_TBX_EVENT_TEXT;
2595}
2596
2598 XclImpTbxObjBase( rRoot ),
2599 mnValue( 0 ),
2600 mnMin( 0 ),
2601 mnMax( 100 ),
2602 mnStep( 1 ),
2603 mnPageStep( 10 ),
2604 mnOrient( 0 ),
2605 mnThumbWidth( 1 ),
2606 mnScrollFlags( 0 )
2607{
2608}
2609
2611{
2612 rStrm.Ignore( 4 );
2613 mnValue = rStrm.ReaduInt16();
2614 mnMin = rStrm.ReaduInt16();
2615 mnMax = rStrm.ReaduInt16();
2616 mnStep = rStrm.ReaduInt16();
2617 mnPageStep = rStrm.ReaduInt16();
2618 mnOrient = rStrm.ReaduInt16();
2619 mnThumbWidth = rStrm.ReaduInt16();
2620 mnScrollFlags = rStrm.ReaduInt16();
2621}
2622
2623void XclImpTbxObjScrollableBase::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2624{
2625 switch( nSubRecId )
2626 {
2627 case EXC_ID_OBJSBS:
2628 ReadSbs( rStrm );
2629 break;
2630 case EXC_ID_OBJSBSFMLA:
2631 ReadCellLinkFormula( rStrm, false );
2632 break;
2633 default:
2634 XclImpTbxObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2635 }
2636}
2637
2640{
2641}
2642
2643void XclImpSpinButtonObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2644{
2646 ReadSbs( rStrm );
2647 ReadName5( rStrm, nNameLen );
2648 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2649 ReadCellLinkFormula( rStrm, true );
2650}
2651
2653{
2654 // Calc's "Border" property is not the 3D/flat style effect in Excel (#i34712#)
2655 rPropSet.SetProperty( "Border", css::awt::VisualEffect::NONE );
2656 rPropSet.SetProperty< sal_Int32 >( "DefaultSpinValue", mnValue );
2657 rPropSet.SetProperty< sal_Int32 >( "SpinValueMin", mnMin );
2658 rPropSet.SetProperty< sal_Int32 >( "SpinValueMax", mnMax );
2659 rPropSet.SetProperty< sal_Int32 >( "SpinIncrement", mnStep );
2660
2661 // Excel spin buttons always vertical
2662 rPropSet.SetProperty( "Orientation", css::awt::ScrollBarOrientation::VERTICAL );
2663}
2664
2666{
2667 return "com.sun.star.form.component.SpinButton";
2668}
2669
2671{
2672 return EXC_TBX_EVENT_VALUE;
2673}
2674
2677{
2678}
2679
2680void XclImpScrollBarObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2681{
2683 ReadSbs( rStrm );
2684 ReadName5( rStrm, nNameLen );
2685 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2686 ReadCellLinkFormula( rStrm, true );
2687}
2688
2690{
2691 // Calc's "Border" property is not the 3D/flat style effect in Excel (#i34712#)
2692 rPropSet.SetProperty( "Border", css::awt::VisualEffect::NONE );
2693 rPropSet.SetProperty< sal_Int32 >( "DefaultScrollValue", mnValue );
2694 rPropSet.SetProperty< sal_Int32 >( "ScrollValueMin", mnMin );
2695 rPropSet.SetProperty< sal_Int32 >( "ScrollValueMax", mnMax );
2696 rPropSet.SetProperty< sal_Int32 >( "LineIncrement", mnStep );
2697 rPropSet.SetProperty< sal_Int32 >( "BlockIncrement", mnPageStep );
2698 rPropSet.SetProperty( "VisibleSize", ::std::min< sal_Int32 >( mnPageStep, 1 ) );
2699
2700 namespace AwtScrollOrient = ::com::sun::star::awt::ScrollBarOrientation;
2701 sal_Int32 nApiOrient = ::get_flagvalue( mnOrient, EXC_OBJ_SCROLLBAR_HOR, AwtScrollOrient::HORIZONTAL, AwtScrollOrient::VERTICAL );
2702 rPropSet.SetProperty( "Orientation", nApiOrient );
2703}
2704
2706{
2707 return "com.sun.star.form.component.ScrollBar";
2708}
2709
2711{
2712 return EXC_TBX_EVENT_VALUE;
2713}
2714
2717 mnEntryCount( 0 ),
2718 mnSelEntry( 0 ),
2719 mnListFlags( 0 ),
2720 mnEditObjId( 0 ),
2721 mbHasDefFontIdx( false )
2722{
2723}
2724
2726{
2728 mnEntryCount = rStrm.ReaduInt16();
2729 mnSelEntry = rStrm.ReaduInt16();
2730 mnListFlags = rStrm.ReaduInt16();
2731 mnEditObjId = rStrm.ReaduInt16();
2732}
2733
2735{
2736 // border style
2737 namespace AwtVisualEffect = ::com::sun::star::awt::VisualEffect;
2738 sal_Int16 nApiBorder = ::get_flagvalue( mnListFlags, EXC_OBJ_LISTBOX_FLAT, AwtVisualEffect::FLAT, AwtVisualEffect::LOOK3D );
2739 rPropSet.SetProperty( "Border", nApiBorder );
2740
2741 // font formatting
2742 if( mbHasDefFontIdx )
2744 else
2746}
2747
2749 XclImpTbxObjListBase( rRoot )
2750{
2751}
2752
2753void XclImpListBoxObj::ReadFullLbsData( XclImpStream& rStrm, std::size_t nRecLeft )
2754{
2755 std::size_t nRecEnd = rStrm.GetRecPos() + nRecLeft;
2756 ReadLbsData( rStrm );
2757 OSL_ENSURE( (rStrm.GetRecPos() == nRecEnd) || (rStrm.GetRecPos() + mnEntryCount == nRecEnd),
2758 "XclImpListBoxObj::ReadFullLbsData - invalid size of OBJLBSDATA record" );
2759 while (rStrm.IsValid())
2760 {
2761 if (rStrm.GetRecPos() >= nRecEnd)
2762 break;
2763 maSelection.push_back( rStrm.ReaduInt8() );
2764 }
2765}
2766
2767void XclImpListBoxObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2768{
2770 ReadSbs( rStrm );
2771 rStrm.Ignore( 18 );
2772 maTextData.maData.mnDefFontIdx = rStrm.ReaduInt16();
2773 rStrm.Ignore( 4 );
2774 ReadName5( rStrm, nNameLen );
2775 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2776 ReadCellLinkFormula( rStrm, true );
2777 ReadFullLbsData( rStrm, rStrm.GetRecLeft() );
2778 mbHasDefFontIdx = true;
2779}
2780
2781void XclImpListBoxObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2782{
2783 switch( nSubRecId )
2784 {
2785 case EXC_ID_OBJLBSDATA:
2786 ReadFullLbsData( rStrm, nSubRecSize );
2787 break;
2788 default:
2789 XclImpTbxObjListBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2790 }
2791}
2792
2794{
2795 // listbox formatting
2796 SetBoxFormatting( rPropSet );
2797
2798 // selection type
2799 sal_uInt8 nSelType = ::extract_value< sal_uInt8 >( mnListFlags, 4, 2 );
2800 bool bMultiSel = nSelType != EXC_OBJ_LISTBOX_SINGLE;
2801 rPropSet.SetBoolProperty( "MultiSelection", bMultiSel );
2802
2803 // selection (do not set, if listbox is linked to a cell)
2804 if( HasCellLink() )
2805 return;
2806
2807 ScfInt16Vec aSelVec;
2808
2809 // multi selection: API expects sequence of list entry indexes
2810 if( bMultiSel )
2811 {
2812 sal_Int16 nIndex = 0;
2813 for( const auto& rItem : maSelection )
2814 {
2815 if( rItem != 0 )
2816 aSelVec.push_back( nIndex );
2817 ++nIndex;
2818 }
2819 }
2820 // single selection: mnSelEntry is one-based, API expects zero-based
2821 else if( mnSelEntry > 0 )
2822 aSelVec.push_back( static_cast< sal_Int16 >( mnSelEntry - 1 ) );
2823
2824 if( !aSelVec.empty() )
2825 {
2826 Sequence<sal_Int16> aSelSeq(aSelVec.data(), static_cast<sal_Int32>(aSelVec.size()));
2827 rPropSet.SetProperty( "DefaultSelection", aSelSeq );
2828 }
2829}
2830
2832{
2833 return "com.sun.star.form.component.ListBox";
2834}
2835
2837{
2838 return EXC_TBX_EVENT_CHANGE;
2839}
2840
2842 XclImpTbxObjListBase( rRoot ),
2843 mnLeft( 0 ),
2844 mnTop( 0 ),
2845 mnRight( 0 ),
2846 mnBottom( 0 ),
2847 mnDropDownFlags( 0 ),
2848 mnLineCount( 0 ),
2849 mnMinWidth( 0 )
2850{
2851}
2852
2854{
2855 return ::extract_value< sal_uInt8 >( mnDropDownFlags, 0, 2 );
2856}
2857
2859{
2860 ReadLbsData( rStrm );
2861 mnDropDownFlags = rStrm.ReaduInt16();
2862 mnLineCount = rStrm.ReaduInt16();
2863 mnMinWidth = rStrm.ReaduInt16();
2864 maTextData.maData.mnTextLen = rStrm.ReaduInt16();
2866 // dropdowns of auto-filters have 'simple' style, they don't have a text area
2868 SetProcessSdrObj( false );
2869}
2870
2871void XclImpDropDownObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 /*nMacroSize*/ )
2872{
2874 ReadSbs( rStrm );
2875 rStrm.Ignore( 18 );
2876 maTextData.maData.mnDefFontIdx = rStrm.ReaduInt16();
2877 rStrm.Ignore( 14 );
2878 mnLeft = rStrm.ReaduInt16();
2879 mnTop = rStrm.ReaduInt16();
2880 mnRight = rStrm.ReaduInt16();
2881 mnBottom = rStrm.ReaduInt16();
2882 rStrm.Ignore( 4 );
2883 ReadName5( rStrm, nNameLen );
2884 ReadMacro5( rStrm, rStrm.ReaduInt16() ); // first macro size invalid and unused
2885 ReadCellLinkFormula( rStrm, true );
2887 mbHasDefFontIdx = true;
2888}
2889
2890void XclImpDropDownObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
2891{
2892 switch( nSubRecId )
2893 {
2894 case EXC_ID_OBJLBSDATA:
2896 break;
2897 default:
2898 XclImpTbxObjListBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
2899 }
2900}
2901
2903{
2904 // dropdown listbox formatting
2905 SetBoxFormatting( rPropSet );
2906 // enable dropdown button
2907 rPropSet.SetBoolProperty( "Dropdown", true );
2908 // dropdown line count
2909 rPropSet.SetProperty( "LineCount", mnLineCount );
2910
2912 {
2913 // text of editable combobox
2914 if( maTextData.mxString )
2915 rPropSet.SetStringProperty( "DefaultText", maTextData.mxString->GetText() );
2916 }
2917 else
2918 {
2919 // selection (do not set, if dropdown is linked to a cell)
2920 if( !HasCellLink() && (mnSelEntry > 0) )
2921 {
2922 Sequence< sal_Int16 > aSelSeq{ o3tl::narrowing<sal_Int16>(mnSelEntry - 1) };
2923 rPropSet.SetProperty( "DefaultSelection", aSelSeq );
2924 }
2925 }
2926}
2927
2929{
2931 OUString( "com.sun.star.form.component.ComboBox" ) :
2932 OUString( "com.sun.star.form.component.ListBox" );
2933}
2934
2936{
2938}
2939
2941 XclImpRectObj( rRoot ),
2943 mnStorageId( 0 ),
2944 mnCtlsStrmPos( 0 ),
2945 mnCtlsStrmSize( 0 ),
2946 mbEmbedded( false ),
2947 mbLinked( false ),
2948 mbSymbol( false ),
2949 mbControl( false ),
2950 mbUseCtlsStrm( false )
2951{
2952 SetAreaObj( true );
2953 SetSimpleMacro( true );
2954 SetCustomDffObj( true );
2955}
2956
2958{
2959 OUStringBuffer aStrgName;
2960 if( (mbEmbedded || mbLinked) && !mbControl && (mnStorageId > 0) )
2961 {
2962 aStrgName = mbEmbedded ? std::u16string_view(u"" EXC_STORAGE_OLE_EMBEDDED) : std::u16string_view(u"" EXC_STORAGE_OLE_LINKED);
2963 static const char spcHexChars[] = "0123456789ABCDEF";
2964 for( sal_uInt8 nIndex = 32; nIndex > 0; nIndex -= 4 )
2965 aStrgName.append(OUStringChar( spcHexChars[ ::extract_value< sal_uInt8 >( mnStorageId, nIndex - 4, 4 ) ] ));
2966 }
2967 return aStrgName.makeStringAndClear();
2968}
2969
2970void XclImpPictureObj::DoReadObj3( XclImpStream& rStrm, sal_uInt16 nMacroSize )
2971{
2972 sal_uInt16 nLinkSize;
2974 rStrm.Ignore( 6 );
2975 nLinkSize = rStrm.ReaduInt16();
2976 rStrm.Ignore( 2 );
2977 ReadFlags3( rStrm );
2978 ReadMacro3( rStrm, nMacroSize );
2979 ReadPictFmla( rStrm, nLinkSize );
2980
2981 if( (rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord() )
2983}
2984
2985void XclImpPictureObj::DoReadObj4( XclImpStream& rStrm, sal_uInt16 nMacroSize )
2986{
2987 sal_uInt16 nLinkSize;
2989 rStrm.Ignore( 6 );
2990 nLinkSize = rStrm.ReaduInt16();
2991 rStrm.Ignore( 2 );
2992 ReadFlags3( rStrm );
2993 ReadMacro4( rStrm, nMacroSize );
2994 ReadPictFmla( rStrm, nLinkSize );
2995
2996 if( (rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord() )
2998}
2999
3000void XclImpPictureObj::DoReadObj5( XclImpStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize )
3001{
3002 sal_uInt16 nLinkSize;
3004 rStrm.Ignore( 6 );
3005 nLinkSize = rStrm.ReaduInt16();
3006 rStrm.Ignore( 2 );
3007 ReadFlags3( rStrm );
3008 rStrm.Ignore( 4 );
3009 ReadName5( rStrm, nNameLen );
3010 ReadMacro5( rStrm, nMacroSize );
3011 ReadPictFmla( rStrm, nLinkSize );
3012
3013 if( (rStrm.GetNextRecId() == EXC_ID3_IMGDATA) && rStrm.StartNextRecord() )
3014 {
3015 // page background is stored as hidden picture with name "__BkgndObj"
3016 if ( IsHidden() && (GetObjName() == "__BkgndObj") )
3018 else
3020 }
3021}
3022
3023void XclImpPictureObj::DoReadObj8SubRec( XclImpStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize )
3024{
3025 switch( nSubRecId )
3026 {
3027 case EXC_ID_OBJFLAGS:
3028 ReadFlags8( rStrm );
3029 break;
3030 case EXC_ID_OBJPICTFMLA:
3031 ReadPictFmla( rStrm, rStrm.ReaduInt16() );
3032 break;
3033 default:
3034 XclImpDrawObjBase::DoReadObj8SubRec( rStrm, nSubRecId, nSubRecSize );
3035 }
3036}
3037
3039{
3040 // try to create an OLE object or form control
3041 rtl::Reference<SdrObject> xSdrObj( rDffConv.CreateSdrObject( *this, rAnchorRect ) );
3042
3043 // insert a graphic replacement for unsupported ole object ( if none already
3044 // exists ) Hmm ok, it's possibly that there has been some imported
3045 // graphic at a base level but unlikely, normally controls have a valid
3046 // preview in the IMGDATA record ( see below )
3047 // It might be possible to push such an imported graphic up to this
3048 // XclImpPictureObj instance but there are so many layers of indirection I
3049 // don't see an easy way. This way at least ensures that we can
3050 // avoid a 'blank' shape that can result from a failed control import
3051 if ( !xSdrObj && IsOcxControl() && maGraphic.GetType() == GraphicType::NONE )
3052 {
3053 const_cast< XclImpPictureObj* >( this )->maGraphic =
3055 }
3056 // no OLE - create a plain picture from IMGDATA record data
3057 if( !xSdrObj && (maGraphic.GetType() != GraphicType::NONE) )
3058 {
3059 xSdrObj =
3060 new SdrGrafObj(
3061 *GetDoc().GetDrawLayer(),
3062 maGraphic,
3063 rAnchorRect);
3064 ConvertRectStyle( *xSdrObj );
3065 }
3066
3067 rDffConv.Progress();
3068 return xSdrObj;
3069}
3070
3072{
3073 if( IsOcxControl() )
3074 {
3075 OUString sName( GetObjectManager().GetOleNameOverride( GetTab(), GetObjId() ) );
3076 if (!sName.isEmpty())
3077 return sName;
3078 }
3080}
3081
3083{
3084 if( IsOcxControl() )
3085 {
3086 // do not call XclImpRectObj::DoPreProcessSdrObj(), it would trace missing "printable" feature
3087 ProcessControl( *this );
3088 }
3089 else if( mbEmbedded || mbLinked )
3090 {
3091 // trace missing "printable" feature
3092 XclImpRectObj::DoPreProcessSdrObj( rDffConv, rSdrObj );
3093
3094 SfxObjectShell* pDocShell = GetDocShell();
3095 SdrOle2Obj* pOleSdrObj = dynamic_cast< SdrOle2Obj* >( &rSdrObj );
3096 if( pOleSdrObj && pDocShell )
3097 {
3099 Reference< XEmbeddedObject > xEmbObj = pOleSdrObj->GetObjRef();
3100 OUString aOldName( pOleSdrObj->GetPersistName() );
3101
3102 /* The object persistence should be already in the storage, but
3103 the object still might not be inserted into the container. */
3104 if( rEmbObjCont.HasEmbeddedObject( aOldName ) )
3105 {
3106 if( !rEmbObjCont.HasEmbeddedObject( xEmbObj ) )
3107 // filter code is allowed to call the following method
3108 rEmbObjCont.AddEmbeddedObject( xEmbObj, aOldName );
3109 }
3110 else
3111 {
3112 /* If the object is still not in container it must be inserted
3113 there, the name must be generated in this case. */
3114 OUString aNewName;
3115 rEmbObjCont.InsertEmbeddedObject( xEmbObj, aNewName );
3116 if( aOldName != aNewName )
3117 // SetPersistName, not SetName
3118 pOleSdrObj->SetPersistName( aNewName );
3119 }
3120 }
3121 }
3122}
3123
3125{
3126 sal_uInt16 nFlags;
3127 nFlags = rStrm.ReaduInt16();
3129}
3130
3132{
3133 sal_uInt16 nFlags;
3134 nFlags = rStrm.ReaduInt16();
3138 OSL_ENSURE( mbControl || !mbUseCtlsStrm, "XclImpPictureObj::ReadFlags8 - CTLS stream for controls only" );
3140}
3141
3142void XclImpPictureObj::ReadPictFmla( XclImpStream& rStrm, sal_uInt16 nLinkSize )
3143{
3144 std::size_t nLinkEnd = rStrm.GetRecPos() + nLinkSize;
3145 if( nLinkSize >= 6 )
3146 {
3147 sal_uInt16 nFmlaSize;
3148 nFmlaSize = rStrm.ReaduInt16();
3149 OSL_ENSURE( nFmlaSize > 0, "XclImpPictureObj::ReadPictFmla - missing link formula" );
3150 // BIFF3/BIFF4 do not support storages, nothing to do here
3151 if( (nFmlaSize > 0) && (GetBiff() >= EXC_BIFF5) )
3152 {
3153 rStrm.Ignore( 4 );
3155 nToken = rStrm.ReaduInt8();
3156
3157 // different processing for linked vs. embedded OLE objects
3159 {
3160 mbLinked = true;
3161 switch( GetBiff() )
3162 {
3163 case EXC_BIFF5:
3164 {
3165 sal_Int16 nRefIdx;
3166 sal_uInt16 nNameIdx;
3167 nRefIdx = rStrm.ReadInt16();
3168 rStrm.Ignore( 8 );
3169 nNameIdx = rStrm.ReaduInt16();
3170 rStrm.Ignore( 12 );
3171 const ExtName* pExtName = GetOldRoot().pExtNameBuff->GetNameByIndex( nRefIdx, nNameIdx );
3172 if( pExtName && pExtName->IsOLE() )
3173 mnStorageId = pExtName->nStorageId;
3174 }
3175 break;
3176 case EXC_BIFF8:
3177 {
3178 sal_uInt16 nXti, nExtName;
3179 nXti = rStrm.ReaduInt16();
3180 nExtName = rStrm.ReaduInt16();
3181 const XclImpExtName* pExtName = GetLinkManager().GetExternName( nXti, nExtName );
3182 if( pExtName && (pExtName->GetType() == xlExtOLE) )
3183 mnStorageId = pExtName->GetStorageId();
3184 }
3185 break;
3186 default:
3188 }
3189 }
3191 {
3192 mbEmbedded = true;
3193 OSL_ENSURE( nFmlaSize == 5, "XclImpPictureObj::ReadPictFmla - unexpected formula size" );
3194 rStrm.Ignore( nFmlaSize - 1 ); // token ID already read
3195 if( nFmlaSize & 1 )
3196 rStrm.Ignore( 1 ); // padding byte
3197
3198 // a class name may follow inside the picture link
3199 if( rStrm.GetRecPos() + 2 <= nLinkEnd )
3200 {
3201 sal_uInt16 nLen = rStrm.ReaduInt16();
3202 if( nLen > 0 )
3203 maClassName = (GetBiff() == EXC_BIFF8) ? rStrm.ReadUniString( nLen ) : rStrm.ReadRawByteString( nLen );
3204 }
3205 }
3206 // else: ignore other formulas, e.g. pictures linked to cell ranges
3207 }
3208 }
3209
3210 // seek behind picture link data
3211 rStrm.Seek( nLinkEnd );
3212
3213 // read additional data for embedded OLE objects following the picture link
3214 if( IsOcxControl() )
3215 {
3216 // #i26521# form controls to be ignored
3217 if( maClassName == "Forms.HTML:Hidden.1" )
3218 {
3219 SetProcessSdrObj( false );
3220 return;
3221 }
3222
3223 if( rStrm.GetRecLeft() <= 8 ) return;
3224
3225 // position and size of control data in 'Ctls' stream
3226 mnCtlsStrmPos = static_cast< std::size_t >( rStrm.ReaduInt32() );
3227 mnCtlsStrmSize = static_cast< std::size_t >( rStrm.ReaduInt32() );
3228
3229 if( rStrm.GetRecLeft() <= 8 ) return;
3230
3231 // additional string (16-bit characters), e.g. for progress bar control
3232 sal_uInt32 nAddStrSize;
3233 nAddStrSize = rStrm.ReaduInt32();
3234 OSL_ENSURE( rStrm.GetRecLeft() >= nAddStrSize + 4, "XclImpPictureObj::ReadPictFmla - missing data" );
3235 if( rStrm.GetRecLeft() >= nAddStrSize + 4 )
3236 {
3237 rStrm.Ignore( nAddStrSize );
3238 // cell link and source range
3239 ReadCellLinkFormula( rStrm, true );
3241 }
3242 }
3243 else if( mbEmbedded && (rStrm.GetRecLeft() >= 4) )
3244 {
3245 mnStorageId = rStrm.ReaduInt32();
3246 }
3247}
3248
3249// DFF stream conversion ======================================================
3250
3251void XclImpSolverContainer::InsertSdrObjectInfo( SdrObject& rSdrObj, sal_uInt32 nDffShapeId, ShapeFlag nDffFlags )
3252{
3253 if( nDffShapeId > 0 )
3254 {
3255 maSdrInfoMap[ nDffShapeId ].Set( &rSdrObj, nDffFlags );
3256 maSdrObjMap[ &rSdrObj ] = nDffShapeId;
3257 }
3258}
3259
3261{
3262 // remove info of passed object from the maps
3263 XclImpSdrObjMap::iterator aIt = maSdrObjMap.find( &rSdrObj );
3264 if( aIt != maSdrObjMap.end() )
3265 {
3266 maSdrInfoMap.erase( aIt->second );
3267 maSdrObjMap.erase( aIt );
3268 }
3269
3270 // remove info of all child objects of a group object
3271 if( SdrObjGroup* pGroupObj = dynamic_cast< SdrObjGroup* >( &rSdrObj ) )
3272 {
3273 if( SdrObjList* pSubList = pGroupObj->GetSubList() )
3274 {
3275 // iterate flat over the list because this function already works recursively
3276 SdrObjListIter aObjIt( pSubList, SdrIterMode::Flat );
3277 for( SdrObject* pChildObj = aObjIt.Next(); pChildObj; pChildObj = aObjIt.Next() )
3278 RemoveSdrObjectInfo( *pChildObj );
3279 }
3280 }
3281}
3282
3284{
3285 for (auto const & pRule : aCList)
3286 {
3287 UpdateConnection( pRule->nShapeA, pRule->pAObj, &pRule->nSpFlagsA );
3288 UpdateConnection( pRule->nShapeB, pRule->pBObj, &pRule->nSpFlagsB );
3289 UpdateConnection( pRule->nShapeC, pRule->pCObj );
3290 }
3291}
3292
3294{
3295 aCList.clear();
3296 maSdrInfoMap.clear();
3297 maSdrObjMap.clear();
3298}
3299
3300void XclImpSolverContainer::UpdateConnection( sal_uInt32 nDffShapeId, SdrObject*& rpSdrObj, ShapeFlag* pnDffFlags )
3301{
3302 XclImpSdrInfoMap::const_iterator aIt = maSdrInfoMap.find( nDffShapeId );
3303 if( aIt != maSdrInfoMap.end() )
3304 {
3305 rpSdrObj = aIt->second.mpSdrObj;
3306 if( pnDffFlags )
3307 *pnDffFlags = aIt->second.mnDffFlags;
3308 }
3309}
3310
3312 SvxMSDffManager( rDffStrm, rRoot.GetBasePath(), 0, nullptr, rRoot.GetDoc().GetDrawLayer(), 1440, COL_DEFAULT, nullptr ),
3313 XclImpRoot( rRoot )
3314{
3316}
3317
3319{
3320}
3321
3322bool XclImpSimpleDffConverter::GetColorFromPalette( sal_uInt16 nIndex, Color& rColor ) const
3323{
3324 Color nColor = GetPalette().GetColor( nIndex );
3325
3326 if( nColor == COL_AUTO )
3327 return false;
3328
3329 rColor = nColor;
3330 return true;
3331}
3332
3334 XclImpDrawing& rDrawing, SdrModel& rSdrModel, SdrPage& rSdrPage ) :
3335 mrDrawing( rDrawing ),
3336 mrSdrModel( rSdrModel ),
3337 mrSdrPage( rSdrPage ),
3338 mnLastCtrlIndex( -1 ),
3339 mbHasCtrlForm( false )
3340{
3341}
3342
3343constexpr OUStringLiteral gaStdFormName( u"Standard" );
3344
3346 XclImpSimpleDffConverter( rRoot, rDffStrm ),
3347 oox::ole::MSConvertOCXControls( rRoot.GetDocShell()->GetModel() ),
3348 mnOleImpFlags( 0 ),
3350{
3351 const SvtFilterOptions& rFilterOpt = SvtFilterOptions::Get();
3352 if( rFilterOpt.IsMathType2Math() )
3354 if( rFilterOpt.IsWinWord2Writer() )
3356 if( rFilterOpt.IsPowerPoint2Impress() )
3358
3359 // try to open the 'Ctls' storage stream containing OCX control properties
3361
3362 // default text margin (convert EMU to drawing layer units)
3365}
3366
3368{
3369}
3370
3371OUString XclImpObjectManager::GetOleNameOverride( SCTAB nTab, sal_uInt16 nObjId )
3372{
3373 OUString sOleName;
3374 OUString sCodeName = GetExtDocOptions().GetCodeName( nTab );
3375
3376 if (mxOleCtrlNameOverride.is() && mxOleCtrlNameOverride->hasByName(sCodeName))
3377 {
3378 Reference< XIndexContainer > xIdToOleName;
3379 mxOleCtrlNameOverride->getByName( sCodeName ) >>= xIdToOleName;
3380 xIdToOleName->getByIndex( nObjId ) >>= sOleName;
3381 }
3382
3383 return sOleName;
3384}
3385
3386void XclImpDffConverter::StartProgressBar( std::size_t nProgressSize )
3387{
3388 mxProgress = std::make_shared<ScfProgressBar>( GetDocShell(), STR_PROGRESS_CALCULATING );
3389 mxProgress->AddSegment( nProgressSize );
3390 mxProgress->Activate();
3391}
3392
3393void XclImpDffConverter::Progress( std::size_t nDelta )
3394{
3395 OSL_ENSURE( mxProgress, "XclImpDffConverter::Progress - invalid call, no progress bar" );
3396 mxProgress->Progress( nDelta );
3397}
3398
3400{
3401 XclImpDffConvDataRef xConvData = std::make_shared<XclImpDffConvData>( rDrawing, rSdrModel, rSdrPage );
3402 maDataStack.push_back( xConvData );
3403 SetModel( &xConvData->mrSdrModel, 1440 );
3404}
3405
3407{
3408 if( !rDrawObj.IsProcessSdrObj() )
3409 return;
3410
3411 const XclObjAnchor* pAnchor = rDrawObj.GetAnchor();
3412 if(!pAnchor)
3413 return;
3414
3415 tools::Rectangle aAnchorRect = GetConvData().mrDrawing.CalcAnchorRect( *pAnchor, false );
3416 if( rDrawObj.IsValidSize( aAnchorRect ) )
3417 {
3418 // CreateSdrObject() recursively creates embedded child objects
3419 rtl::Reference<SdrObject> xSdrObj( rDrawObj.CreateSdrObject( *this, aAnchorRect, false ) );
3420 if( xSdrObj )
3421 rDrawObj.PreProcessSdrObject( *this, *xSdrObj );
3422 // call InsertSdrObject() also, if SdrObject is missing
3423 InsertSdrObject( rObjList, rDrawObj, xSdrObj.get() );
3424 }
3425}
3426
3428{
3429 SdrPage& rSdrPage = GetConvData().mrSdrPage;
3430 for( const auto& rxDrawObj : rDrawObjs )
3431 ProcessObject( rSdrPage, *rxDrawObj );
3432}
3433
3435{
3436 if( rDffStrm.TellEnd() > 0 )
3437 {
3438 rDffStrm.Seek( STREAM_SEEK_TO_BEGIN );
3439 DffRecordHeader aHeader;
3440 ReadDffRecordHeader( rDffStrm, aHeader );
3441 OSL_ENSURE( aHeader.nRecType == DFF_msofbtDgContainer, "XclImpDffConverter::ProcessDrawing - unexpected record" );
3442 if( aHeader.nRecType == DFF_msofbtDgContainer )
3443 ProcessDgContainer( rDffStrm, aHeader );
3444 }
3445}
3446
3448{
3449 OSL_ENSURE( !maDataStack.empty(), "XclImpDffConverter::FinalizeDrawing - no drawing manager on stack" );
3450 maDataStack.pop_back();
3451 // restore previous model at core DFF converter
3452 if( !maDataStack.empty() )
3453 SetModel( &maDataStack.back()->mrSdrModel, 1440 );
3454}
3455
3457{
3459 return;
3462}
3463
3465{
3467
3468 OUString aServiceName = rTbxObj.GetServiceName();
3469 if( SupportsOleObjects() && !aServiceName.isEmpty() ) try
3470 {
3471 // create the form control from scratch
3472 Reference< XFormComponent > xFormComp( ScfApiHelper::CreateInstance( GetDocShell(), aServiceName ), UNO_QUERY_THROW );
3473 // set controls form, needed in virtual function InsertControl()
3475 // try to insert the control into the form
3476 css::awt::Size aDummySize;
3477 Reference< XShape > xShape;
3478 XclImpDffConvData& rConvData = GetConvData();
3479 if( rConvData.mxCtrlForm.is() && InsertControl( xFormComp, aDummySize, &xShape, true ) )
3480 {
3481 xSdrObj = rTbxObj.CreateSdrObjectFromShape( xShape, rAnchorRect );
3482 // try to attach a macro to the control
3483 ScriptEventDescriptor aDescriptor;
3484 if( (rConvData.mnLastCtrlIndex >= 0) && rTbxObj.FillMacroDescriptor( aDescriptor ) )
3485 {
3487 Reference< XEventAttacherManager > xEventMgr( rConvData.mxCtrlForm, UNO_QUERY_THROW );
3488 xEventMgr->registerScriptEvent( rConvData.mnLastCtrlIndex, aDescriptor );
3489 }
3490 }
3491 }
3492 catch( const Exception& )
3493 {
3494 }
3495
3496 return xSdrObj;
3497}
3498
3500{
3502
3503 if( SupportsOleObjects() )
3504 {
3505 if( rPicObj.IsOcxControl() )
3506 {
3507 if( mxCtlsStrm.is() ) try
3508 {
3509 /* set controls form, needed in virtual function InsertControl()
3510 called from ReadOCXExcelKludgeStream() */
3512
3513 // read from mxCtlsStrm into xShape, insert the control model into the form
3514 Reference< XShape > xShape;
3515 if( GetConvData().mxCtrlForm.is() )
3516 {
3517 Reference< XFormComponent > xFComp;
3518 ReadOCXCtlsStream( mxCtlsStrm, xFComp, rPicObj.GetCtlsStreamPos(), rPicObj.GetCtlsStreamSize() );
3519 // recreate the method formerly known as ReadOCXExcelKludgeStream()
3520 if ( xFComp.is() )
3521 {
3522 css::awt::Size aSz; // not used in import
3523 ScfPropertySet aPropSet( xFComp );
3524 aPropSet.SetStringProperty( "Name", rPicObj.GetObjName() );
3525 InsertControl( xFComp, aSz,&xShape,true);
3526 xSdrObj = rPicObj.CreateSdrObjectFromShape( xShape, rAnchorRect );
3527 }
3528 }
3529 }
3530 catch( const Exception& )
3531 {
3532 }
3533 }
3534 else
3535 {
3536 SfxObjectShell* pDocShell = GetDocShell();
3538 OUString aStrgName = rPicObj.GetOleStorageName();
3539 if( pDocShell && xSrcStrg.is() && (!aStrgName.isEmpty()) )
3540 {
3541 // first try to resolve graphic from DFF storage
3542 Graphic aGraphic;
3543 tools::Rectangle aVisArea;
3544 if( !GetBLIP( GetPropertyValue( DFF_Prop_pib, 0 ), aGraphic, &aVisArea ) )
3545 {
3546 // if not found, use graphic from object (imported from IMGDATA record)
3547 aGraphic = rPicObj.GetGraphic();
3548 }
3549 if( aGraphic.GetType() != GraphicType::NONE )
3550 {
3551 ErrCode nError = ERRCODE_NONE;
3552 namespace cssea = ::com::sun::star::embed::Aspects;
3553 sal_Int64 nAspects = rPicObj.IsSymbol() ? cssea::MSOLE_ICON : cssea::MSOLE_CONTENT;
3554 xSdrObj =
3556 GetConvData().mrSdrModel,
3557 aStrgName,
3558 xSrcStrg,
3559 pDocShell->GetStorage(),
3560 aGraphic,
3561 rAnchorRect,
3562 aVisArea,
3563 nullptr,
3564 nError,
3566 nAspects,
3567 GetRoot().GetMedium().GetBaseURL());
3568 }
3569 }
3570 }
3571 }
3572
3573 return xSdrObj;
3574}
3575
3577{
3579}
3580
3581// virtual functions ----------------------------------------------------------
3582
3584 DffRecordHeader& rHeader, DffObjData& rObjData )
3585{
3586 // find the OBJ record data related to the processed shape
3587 XclImpDffConvData& rConvData = GetConvData();
3588 XclImpDrawObjBase* pDrawObj = rConvData.mrDrawing.FindDrawObj( rObjData.rSpHd ).get();
3589 if(!pDrawObj)
3590 return;
3591
3592 OSL_ENSURE( rHeader.nRecType == DFF_msofbtClientAnchor, "XclImpDffConverter::ProcessClientAnchor2 - no client anchor record" );
3593 XclObjAnchor aAnchor;
3594 rHeader.SeekToContent( rDffStrm );
3595 sal_uInt8 nFlags(0);
3596 rDffStrm.ReadUChar( nFlags );
3597 rDffStrm.SeekRel( 1 ); // flags
3598 rDffStrm >> aAnchor; // anchor format equal to BIFF5 OBJ records
3599
3600 if (!rDffStrm.good())
3601 {
3602 SAL_WARN("sc.filter", "ProcessClientAnchor2 short read");
3603 return;
3604 }
3605
3606 pDrawObj->SetAnchor( aAnchor );
3607 rObjData.aChildAnchor = rConvData.mrDrawing.CalcAnchorRect( aAnchor, true );
3608 rObjData.bChildAnchor = true;
3609 // page anchoring is the best approximation we have if mbMove
3610 // is set
3611 rObjData.bPageAnchor = ( nFlags & 0x1 );
3612}
3613
3614namespace {
3615
3616struct XclImpDrawObjClientData : public SvxMSDffClientData
3617{
3618 const XclImpDrawObjBase* m_pTopLevelObj;
3619
3620 XclImpDrawObjClientData()
3621 : m_pTopLevelObj(nullptr)
3622 {
3623 }
3624 virtual void NotifyFreeObj(SdrObject*) override {}
3625};
3626
3627}
3628
3630 SvxMSDffClientData& rClientData, tools::Rectangle& /*rTextRect*/, SdrObject* pOldSdrObj )
3631{
3632 XclImpDffConvData& rConvData = GetConvData();
3633
3634 /* pOldSdrObj passes a generated SdrObject. This function owns this object
3635 and can modify it. The function has either to return it back to caller
3636 or to delete it by itself. */
3637 rtl::Reference<SdrObject> xSdrObj( pOldSdrObj );
3638
3639 // find the OBJ record data related to the processed shape
3640 XclImpDrawObjRef xDrawObj = rConvData.mrDrawing.FindDrawObj( rDffObjData.rSpHd );
3641 const tools::Rectangle& rAnchorRect = rDffObjData.aChildAnchor;
3642
3643 // Do not process the global page group shape
3644 bool bGlobalPageGroup( rDffObjData.nSpFlags & ShapeFlag::Patriarch );
3645 if( !xDrawObj || !xDrawObj->IsProcessSdrObj() || bGlobalPageGroup )
3646 return nullptr; // simply return, xSdrObj will be destroyed
3647
3648 /* Pass pointer to top-level object back to caller. If the processed
3649 object is embedded in a group, the pointer is already set to the
3650 top-level parent object. */
3651 XclImpDrawObjClientData& rDrawObjClientData = static_cast<XclImpDrawObjClientData&>(rClientData);
3652 const bool bIsTopLevel = !rDrawObjClientData.m_pTopLevelObj;
3653 if (bIsTopLevel )
3654 rDrawObjClientData.m_pTopLevelObj = xDrawObj.get();
3655
3656 // connectors don't have to be area objects
3657 if( dynamic_cast< SdrEdgeObj* >( xSdrObj.get() ) )
3658 xDrawObj->SetAreaObj( false );
3659
3660 /* Check for valid size for all objects. Needed to ignore lots of invisible
3661 phantom objects from deleted rows or columns (for performance reasons).
3662 #i30816# Include objects embedded in groups.
3663 #i58780# Ignore group shapes, size is not initialized. */
3664 bool bEmbeddedGroup = !bIsTopLevel && dynamic_cast< SdrObjGroup* >( xSdrObj.get() );
3665 if( !bEmbeddedGroup && !xDrawObj->IsValidSize( rAnchorRect ) )
3666 return nullptr; // simply return, xSdrObj will be destroyed
3667
3668 // set shape information from DFF stream
3669 OUString aObjName = GetPropertyString( DFF_Prop_wzName, rDffStrm );
3670 OUString aHyperlink = ReadHlinkProperty( rDffStrm );
3672 bool bAutoMargin = GetPropertyBool( DFF_Prop_AutoTextMargin );
3673 xDrawObj->SetDffData( rDffObjData, aObjName, aHyperlink, bVisible, bAutoMargin );
3674
3675 /* Connect textbox data (string, alignment, text orientation) to object.
3676 don't ask for a text-ID, DFF export doesn't set one. */
3677 if( XclImpTextObj* pTextObj = dynamic_cast< XclImpTextObj* >( xDrawObj.get() ) )
3678 if( const XclImpObjTextData* pTextData = rConvData.mrDrawing.FindTextData( rDffObjData.rSpHd ) )
3679 pTextObj->SetTextData( *pTextData );
3680
3681 // copy line and fill formatting of TBX form controls from DFF properties
3682 if( XclImpTbxObjBase* pTbxObj = dynamic_cast< XclImpTbxObjBase* >( xDrawObj.get() ) )
3683 pTbxObj->SetDffProperties( *this );
3684
3685 // try to create a custom SdrObject that overwrites the passed object
3686 rtl::Reference<SdrObject> xNewSdrObj( xDrawObj->CreateSdrObject( *this, rAnchorRect, true ) );
3687 if( xNewSdrObj )
3688 xSdrObj = std::move( xNewSdrObj );
3689
3690 // process the SdrObject
3691 if( xSdrObj )
3692 {
3693 // filled without color -> set system window color
3695 xSdrObj->SetMergedItem( XFillColorItem( OUString(), GetPalette().GetColor( EXC_COLOR_WINDOWBACK ) ) );
3696
3697 // additional processing on the SdrObject
3698 xDrawObj->PreProcessSdrObject( *this, *xSdrObj );
3699
3700 /* If the SdrObject will not be inserted into the draw page, delete it
3701 here. Happens e.g. for notes: The PreProcessSdrObject() call above
3702 has inserted the note into the document, and the SdrObject is not
3703 needed anymore. */
3704 if( !xDrawObj->IsInsertSdrObj() )
3705 xSdrObj.clear();
3706 }
3707
3708 if( xSdrObj )
3709 {
3710 /* Store the relation between shape ID and SdrObject for connectors.
3711 Must be done here (and not in InsertSdrObject() function),
3712 otherwise all SdrObjects embedded in groups would be lost. */
3713 rConvData.maSolverCont.InsertSdrObjectInfo( *xSdrObj, xDrawObj->GetDffShapeId(), xDrawObj->GetDffFlags() );
3714
3715 /* If the drawing object is embedded in a group object, call
3716 PostProcessSdrObject() here. For top-level objects this will be
3717 done automatically in InsertSdrObject() but grouped shapes are
3718 inserted into their groups somewhere in the SvxMSDffManager base
3719 class without chance of notification. Unfortunately, now this is
3720 called before the object is really inserted into its group object,
3721 but that should not have any effect for grouped objects. */
3722 if( !bIsTopLevel )
3723 xDrawObj->PostProcessSdrObject( *this, *xSdrObj );
3724 }
3725
3726 return xSdrObj;
3727}
3728
3730{
3731 XclImpDffConvData& rConvData = GetConvData();
3732
3733 /* pOldSdrObj passes a generated SdrObject. This function owns this object
3734 and can modify it. The function has either to return it back to caller
3735 or to delete it by itself. */
3736 rtl::Reference<SdrObject> xSdrObj( pOldSdrObj );
3737
3738 // find the OBJ record data related to the processed shape
3739 XclImpDrawObjRef xDrawObj = rConvData.mrDrawing.FindDrawObj( rDffObjData.rSpHd );
3740
3741 if( xSdrObj && xDrawObj )
3742 {
3743 // cell anchoring
3744 if ( !rDffObjData.bPageAnchor )
3745 ScDrawLayer::SetCellAnchoredFromPosition( *xSdrObj, GetDoc(), xDrawObj->GetTab(), false );
3746 }
3747
3748 return xSdrObj.get();
3749}
3750
3751bool XclImpDffConverter::InsertControl( const Reference< XFormComponent >& rxFormComp,
3752 const css::awt::Size& /*rSize*/, Reference< XShape >* pxShape,
3753 bool /*bFloatingCtrl*/ )
3754{
3755 if( GetDocShell() ) try
3756 {
3757 XclImpDffConvData& rConvData = GetConvData();
3758 Reference< XIndexContainer > xFormIC( rConvData.mxCtrlForm, UNO_QUERY_THROW );
3759 Reference< XControlModel > xCtrlModel( rxFormComp, UNO_QUERY_THROW );
3760
3761 // create the control shape
3762 Reference< XShape > xShape( ScfApiHelper::CreateInstance( GetDocShell(), "com.sun.star.drawing.ControlShape" ), UNO_QUERY_THROW );
3763 Reference< XControlShape > xCtrlShape( xShape, UNO_QUERY_THROW );
3764
3765 // insert the new control into the form
3766 sal_Int32 nNewIndex = xFormIC->getCount();
3767 xFormIC->insertByIndex( nNewIndex, Any( rxFormComp ) );
3768 // on success: store new index of the control for later use (macro events)
3769 rConvData.mnLastCtrlIndex = nNewIndex;
3770
3771 // set control model at control shape and pass back shape to caller
3772 xCtrlShape->setControl( xCtrlModel );
3773 if( pxShape ) *pxShape = xShape;
3774 return true;
3775 }
3776 catch( const Exception& )
3777 {
3778 OSL_FAIL( "XclImpDffConverter::InsertControl - cannot create form control" );
3779 }
3780
3781 return false;
3782}
3783
3784// private --------------------------------------------------------------------
3785
3787{
3788 OSL_ENSURE( !maDataStack.empty(), "XclImpDffConverter::GetConvData - no drawing manager on stack" );
3789 return *maDataStack.back();
3790}
3791
3793{
3794 OSL_ENSURE( !maDataStack.empty(), "XclImpDffConverter::GetConvData - no drawing manager on stack" );
3795 return *maDataStack.back();
3796}
3797
3799{
3800 /* Reads hyperlink data from a complex DFF property. Contents of this
3801 property are equal to the HLINK record, import of this record is
3802 implemented in class XclImpHyperlink. This function has to create an
3803 instance of the XclImpStream class to be able to reuse the
3804 functionality of XclImpHyperlink. */
3805 OUString aString;
3806 sal_uInt32 nBufferSize = GetPropertyValue( DFF_Prop_pihlShape, 0 );
3807 if( (0 < nBufferSize) && (nBufferSize <= 0xFFFF) && SeekToContent( DFF_Prop_pihlShape, rDffStrm ) )
3808 {
3809 // create a faked BIFF record that can be read by XclImpStream class
3810 SvMemoryStream aMemStream;
3811 aMemStream.WriteUInt16( 0 ).WriteUInt16( nBufferSize );
3812
3813 // copy from DFF stream to memory stream
3814 ::std::vector< sal_uInt8 > aBuffer( nBufferSize );
3815 sal_uInt8* pnData = aBuffer.data();
3816 if (rDffStrm.ReadBytes(pnData, nBufferSize) == nBufferSize)
3817 {
3818 aMemStream.WriteBytes(pnData, nBufferSize);
3819
3820 // create BIFF import stream to be able to use XclImpHyperlink class
3821 XclImpStream aXclStrm( aMemStream, GetRoot() );
3822 if( aXclStrm.StartNextRecord() )
3823 aString = XclImpHyperlink::ReadEmbeddedData( aXclStrm );
3824 }
3825 }
3826 return aString;
3827}
3828
3830{
3831 std::size_t nEndPos = rDgHeader.GetRecEndFilePos();
3832 bool isBreak(false);
3833 while (!isBreak && rDffStrm.good() && rDffStrm.Tell() < nEndPos)
3834 {
3835 DffRecordHeader aHeader;
3836 ReadDffRecordHeader( rDffStrm, aHeader );
3837 switch( aHeader.nRecType )
3838 {
3840 isBreak = !ProcessSolverContainer( rDffStrm, aHeader );
3841 break;
3843 isBreak = !ProcessShGrContainer( rDffStrm, aHeader );
3844 break;
3845 default:
3846 isBreak = !aHeader.SeekToEndOfRecord( rDffStrm );
3847 }
3848 }
3849 // seek to end of drawing page container
3850 isBreak = !rDgHeader.SeekToEndOfRecord( rDffStrm );
3851
3852 // #i12638# #i37900# connector rules
3854 rSolverCont.UpdateConnectorRules();
3855 SolveSolver( rSolverCont );
3856 rSolverCont.RemoveConnectorRules();
3857 return !isBreak;
3858}
3859
3861{
3862 std::size_t nEndPos = rShGrHeader.GetRecEndFilePos();
3863 bool isBreak(false);
3864 while (!isBreak && rDffStrm.good() && rDffStrm.Tell() < nEndPos)
3865 {
3866 DffRecordHeader aHeader;
3867 ReadDffRecordHeader( rDffStrm, aHeader );
3868 switch( aHeader.nRecType )
3869 {
3872 isBreak = !ProcessShContainer( rDffStrm, aHeader );
3873 break;
3874 default:
3875 isBreak = !aHeader.SeekToEndOfRecord( rDffStrm );
3876 }
3877 }
3878 // seek to end of shape group container
3879 return rShGrHeader.SeekToEndOfRecord( rDffStrm ) && !isBreak;
3880}
3881
3883{
3884 // solver container wants to read the solver container header again
3885 rSolverHeader.SeekToBegOfRecord( rDffStrm );
3886 // read the entire solver container
3887 ReadSvxMSDffSolverContainer( rDffStrm, GetConvData().maSolverCont );
3888 // seek to end of solver container
3889 return rSolverHeader.SeekToEndOfRecord( rDffStrm );
3890}
3891
3893{
3894 rShHeader.SeekToBegOfRecord( rDffStrm );
3895 tools::Rectangle aDummy;
3896 XclImpDrawObjClientData aDrawObjClientData;
3897 /* The call to ImportObj() creates and returns a new SdrObject for the
3898 processed shape. We take ownership of the returned object here. If the
3899 shape is a group object, all embedded objects are created recursively,
3900 and the returned group object contains them all. ImportObj() calls the
3901 virtual functions ProcessClientAnchor2() and ProcessObj() and writes
3902 the pointer to the related draw object data (OBJ record) into aDrawObjClientData. */
3903 rtl::Reference<SdrObject> xSdrObj( ImportObj( rDffStrm, aDrawObjClientData, aDummy, aDummy, /*nCalledByGroup*/0, /*pShapeId*/nullptr ) );
3904 if (aDrawObjClientData.m_pTopLevelObj && xSdrObj )
3905 InsertSdrObject( GetConvData().mrSdrPage, *aDrawObjClientData.m_pTopLevelObj, xSdrObj.get() );
3906 return rShHeader.SeekToEndOfRecord( rDffStrm );
3907}
3908
3910{
3911 XclImpDffConvData& rConvData = GetConvData();
3912 /* Take ownership of the passed object. If insertion fails (e.g. rDrawObj
3913 states to skip insertion), the object is automatically deleted. */
3914 rtl::Reference<SdrObject> xSdrObj( pSdrObj );
3915 if( xSdrObj && rDrawObj.IsInsertSdrObj() )
3916 {
3917 rObjList.NbcInsertObject( xSdrObj.get() );
3918 // callback to drawing manager for e.g. tracking of used sheet area
3919 rConvData.mrDrawing.OnObjectInserted( rDrawObj );
3920 // callback to drawing object for post processing (use pSdrObj, xSdrObj already released)
3921 rDrawObj.PostProcessSdrObject( *this, *pSdrObj );
3922 }
3923 /* SdrObject still here? Insertion failed, remove data from shape ID map.
3924 The SdrObject will be destructed then. */
3925 if( xSdrObj )
3926 rConvData.maSolverCont.RemoveSdrObjectInfo( *xSdrObj );
3927}
3928
3930{
3931 XclImpDffConvData& rConvData = GetConvData();
3932 if( rConvData.mbHasCtrlForm )
3933 return;
3934
3935 rConvData.mbHasCtrlForm = true;
3936 if( !SupportsOleObjects() )
3937 return;
3938
3939 try
3940 {
3941 Reference< XFormsSupplier > xFormsSupplier( rConvData.mrSdrPage.getUnoPage(), UNO_QUERY_THROW );
3942 Reference< XNameContainer > xFormsNC( xFormsSupplier->getForms(), UNO_SET_THROW );
3943 // find or create the Standard form used to insert the imported controls
3944 if( xFormsNC->hasByName( gaStdFormName ) )
3945 {
3946 xFormsNC->getByName( gaStdFormName ) >>= rConvData.mxCtrlForm;
3947 }
3948 else if( SfxObjectShell* pDocShell = GetDocShell() )
3949 {
3950 rConvData.mxCtrlForm.set( ScfApiHelper::CreateInstance( pDocShell, "com.sun.star.form.component.Form" ), UNO_QUERY_THROW );
3951 xFormsNC->insertByName( gaStdFormName, Any( rConvData.mxCtrlForm ) );
3952 }
3953 }
3954 catch( const Exception& )
3955 {
3956 }
3957}
3958
3959// Drawing manager ============================================================
3960
3961XclImpDrawing::XclImpDrawing( const XclImpRoot& rRoot, bool bOleObjects ) :
3962 XclImpRoot( rRoot ),
3963 mbOleObjs( bOleObjects )
3964{
3965}
3966
3968{
3969}
3970
3972{
3973 Graphic aGraphic;
3974 sal_uInt16 nFormat = rStrm.ReaduInt16();
3975 rStrm.Ignore( 2 );//nEnv
3976 sal_uInt32 nDataSize = rStrm.ReaduInt32();
3977 if( nDataSize <= rStrm.GetRecLeft() )
3978 {
3979 switch( nFormat )
3980 {
3981 case EXC_IMGDATA_WMF: ReadWmf( aGraphic, rStrm ); break;
3982 case EXC_IMGDATA_BMP: ReadBmp( aGraphic, rRoot, rStrm ); break;
3983 default: OSL_FAIL( "XclImpDrawing::ReadImgData - unknown image format" );
3984 }
3985 }
3986 return aGraphic;
3987}
3988
3990{
3991 XclImpDrawObjRef xDrawObj;
3992
3993 /* #i61786# In BIFF8 streams, OBJ records may occur without MSODRAWING
3994 records. In this case, the OBJ records are in BIFF5 format. Do a sanity
3995 check here that there is no DFF data loaded before. */
3996 OSL_ENSURE( maDffStrm.Tell() == 0, "XclImpDrawing::ReadObj - unexpected DFF stream data, OBJ will be ignored" );
3997 if( maDffStrm.Tell() == 0 ) switch( GetBiff() )
3998 {
3999 case EXC_BIFF3:
4000 xDrawObj = XclImpDrawObjBase::ReadObj3( GetRoot(), rStrm );
4001 break;
4002 case EXC_BIFF4:
4003 xDrawObj = XclImpDrawObjBase::ReadObj4( GetRoot(), rStrm );
4004 break;
4005 case EXC_BIFF5:
4006 case EXC_BIFF8:
4007 xDrawObj = XclImpDrawObjBase::ReadObj5( GetRoot(), rStrm );
4008 break;
4009 default:
4011 }
4012
4013 if( xDrawObj )
4014 {
4015 // insert into maRawObjs or into the last open group object
4016 maRawObjs.InsertGrouped( xDrawObj );
4017 // to be able to find objects by ID
4018 maObjMapId[ xDrawObj->GetObjId() ] = xDrawObj;
4019 }
4020}
4021
4023{
4025 // disable internal CONTINUE handling
4026 rStrm.ResetRecord( false );
4027 // read leading MSODRAWING record
4029
4030 // read following drawing records, but do not start following unrelated record
4031 bool bLoop = true;
4032 while( bLoop ) switch( rStrm.GetNextRecId() )
4033 {
4034 case EXC_ID_MSODRAWING:
4036 case EXC_ID_CONT:
4037 rStrm.StartNextRecord();
4039 break;
4040 case EXC_ID_OBJ:
4041 rStrm.StartNextRecord();
4042 ReadObj8( rStrm );
4043 break;
4044 case EXC_ID_TXO:
4045 rStrm.StartNextRecord();
4046 ReadTxo( rStrm );
4047 break;
4048 default:
4049 bLoop = false;
4050 }
4051
4052 // re-enable internal CONTINUE handling
4053 rStrm.ResetRecord( true );
4054}
4055
4057{
4058 /* maObjMap stores objects by position of the client data (OBJ record) in
4059 the DFF stream, which is always behind shape start position of the
4060 passed header. The function upper_bound() finds the first element in
4061 the map whose key is greater than the start position of the header. Its
4062 end position is used to test whether the found object is really related
4063 to the shape. */
4064 XclImpDrawObjRef xDrawObj;
4065 XclImpObjMap::const_iterator aIt = maObjMap.upper_bound( rHeader.GetRecBegFilePos() );
4066 if( (aIt != maObjMap.end()) && (aIt->first <= rHeader.GetRecEndFilePos()) )
4067 xDrawObj = aIt->second;
4068 return xDrawObj;
4069}
4070
4072{
4073 XclImpDrawObjRef xDrawObj;
4074 XclImpObjMapById::const_iterator aIt = maObjMapId.find( nObjId );
4075 if( aIt != maObjMapId.end() )
4076 xDrawObj = aIt->second;
4077 return xDrawObj;
4078}
4079
4081{
4082 /* maTextMap stores textbox data by position of the client data (TXO
4083 record) in the DFF stream, which is always behind shape start position
4084 of the passed header. The function upper_bound() finds the first
4085 element in the map whose key is greater than the start position of the
4086 header. Its end position is used to test whether the found object is
4087 really related to the shape. */
4088 XclImpObjTextMap::const_iterator aIt = maTextMap.upper_bound( rHeader.GetRecBegFilePos() );
4089 if( (aIt != maTextMap.end()) && (aIt->first <= rHeader.GetRecEndFilePos()) )
4090 return aIt->second.get();
4091 return nullptr;
4092}
4093
4095{
4096 // sorted: smallest to largest - looking for smallest contained-in GroupBox
4097 // multimap: allows duplicate key values - may have identical areas.
4098 std::multimap<double, XclImpDrawObjRef> aGroupBoxAreaMap;
4099 for (auto& rGroupBox : maObjMapId)
4100 {
4101 if (rGroupBox.second->GetObjType() != EXC_OBJTYPE_GROUPBOX)
4102 continue;
4103 const tools::Rectangle& rRect = rGroupBox.second->GetDffRect();
4104 const double fArea = double(rRect.GetWidth()) * rRect.GetHeight();
4105 aGroupBoxAreaMap.insert(std::pair<double, XclImpDrawObjRef>(fArea, rGroupBox.second));
4106 }
4107
4108 for (auto& rGroupedObj : maObjMapId)
4109 {
4110 auto pRadioButton = dynamic_cast<XclImpOptionButtonObj*>(rGroupedObj.second.get());
4111 if (!pRadioButton || pRadioButton->IsInGroup())
4112 continue;
4113
4114 OUString sGroupName("autoGroup_");
4115 for (auto& rGroupBox : aGroupBoxAreaMap)
4116 {
4117 assert(pRadioButton->GetTab() == rGroupBox.second->GetTab() && "impossible right?");
4118 if (!rGroupBox.second->GetDffRect().Contains(pRadioButton->GetDffRect()))
4119 continue;
4120
4121 sGroupName = rGroupBox.second->GetObjName();
4122 if (sGroupName.isEmpty())
4123 sGroupName += "autoGroup_" + OUString::number(rGroupBox.second->GetObjId());
4124 // I ASSUME the smallest box wins in MS Word. (otherwise first? last?)
4125 break;
4126 }
4127 pRadioButton->SetStringProperty("GroupName", sGroupName);
4128 }
4129}
4130
4131void XclImpDrawing::SetSkipObj( sal_uInt16 nObjId )
4132{
4133 maSkipObjs.push_back( nObjId );
4134}
4135
4137{
4138 return std::accumulate(maObjMap.begin(), maObjMap.end(), maRawObjs.GetProgressSize(),
4139 [](const std::size_t& rSum, const XclImpObjMap::value_type& rEntry) { return rSum + rEntry.second->GetProgressSize(); });
4140}
4141
4143{
4144 //rhbz#636521, disable undo during conversion. faster, smaller and stops
4145 //temp objects being inserted into the undo list
4146 bool bOrigUndoStatus = rSdrModel.IsUndoEnabled();
4147 rSdrModel.EnableUndo(false);
4148 // register this drawing manager at the passed (global) DFF manager
4149 rDffConv.InitializeDrawing( *this, rSdrModel, rSdrPage );
4150 // process list of objects to be skipped
4151 for( const auto& rSkipObj : maSkipObjs )
4152 if( XclImpDrawObjBase* pDrawObj = FindDrawObj( rSkipObj ).get() )
4153 pDrawObj->SetProcessSdrObj( false );
4154 // process drawing objects without DFF data
4155 rDffConv.ProcessDrawing( maRawObjs );
4156 // process all objects in the DFF stream
4157 rDffConv.ProcessDrawing( maDffStrm );
4158 // assign groups based on being contained in the same GroupBox/sheet
4160 // unregister this drawing manager at the passed (global) DFF manager
4161 rDffConv.FinalizeDrawing();
4162 rSdrModel.EnableUndo(bOrigUndoStatus);
4163}
4164
4165// protected ------------------------------------------------------------------
4166
4168{
4169 OSL_ENSURE( rxDrawObj, "XclImpDrawing::AppendRawObject - unexpected empty reference" );
4170 maRawObjs.push_back( rxDrawObj );
4171}
4172
4173// private --------------------------------------------------------------------
4174
4175void XclImpDrawing::ReadWmf( Graphic& rGraphic, XclImpStream& rStrm ) // static helper
4176{
4177 // extract graphic data from IMGDATA and following CONTINUE records
4178 rStrm.Ignore( 8 );
4179 SvMemoryStream aMemStrm;
4180 rStrm.CopyToStream( aMemStrm, rStrm.GetRecLeft() );
4181 aMemStrm.Seek( STREAM_SEEK_TO_BEGIN );
4182 // import the graphic from memory stream
4183 GDIMetaFile aGDIMetaFile;
4184 if( ::ReadWindowMetafile( aMemStrm, aGDIMetaFile ) )
4185 rGraphic = aGDIMetaFile;
4186}
4187
4188void XclImpDrawing::ReadBmp( Graphic& rGraphic, const XclImpRoot& rRoot, XclImpStream& rStrm ) // static helper
4189{
4190 // extract graphic data from IMGDATA and following CONTINUE records
4191 SvMemoryStream aMemStrm;
4192
4193 /* Excel 3 and 4 seem to write broken BMP data. Usually they write a
4194 DIBCOREHEADER (12 bytes) containing width, height, planes = 1, and
4195 pixel depth = 32 bit. After that, 3 unused bytes are added before the
4196 actual pixel data. This does even confuse Excel 5 and later, which
4197 cannot read the image data correctly. */
4198 if( rRoot.GetBiff() <= EXC_BIFF4 )
4199 {
4200 rStrm.PushPosition();
4201 sal_uInt32 nHdrSize;
4202 sal_uInt16 nWidth, nHeight, nPlanes, nDepth;
4203 nHdrSize = rStrm.ReaduInt32();
4204 nWidth = rStrm.ReaduInt16();
4205 nHeight = rStrm.ReaduInt16();
4206 nPlanes = rStrm.ReaduInt16();
4207 nDepth = rStrm.ReaduInt16();
4208 if( (nHdrSize == 12) && (nPlanes == 1) && (nDepth == 32) )
4209 {
4210 rStrm.Ignore( 3 );
4211 aMemStrm.SetEndian( SvStreamEndian::LITTLE );
4212 aMemStrm.WriteUInt32( nHdrSize ).WriteUInt16( nWidth ).WriteUInt16( nHeight ).WriteUInt16( nPlanes ).WriteUInt16( nDepth );
4213 rStrm.CopyToStream( aMemStrm, rStrm.GetRecLeft() );
4214 }
4215 rStrm.PopPosition();
4216 }
4217
4218 // no special handling above -> just copy the remaining record data
4219 if( aMemStrm.Tell() == 0 )
4220 rStrm.CopyToStream( aMemStrm, rStrm.GetRecLeft() );
4221
4222 // import the graphic from memory stream
4223 aMemStrm.Seek( STREAM_SEEK_TO_BEGIN );
4224 Bitmap aBitmap;
4225 if( ReadDIB(aBitmap, aMemStrm, false) ) // read DIB without file header
4226 rGraphic = BitmapEx(aBitmap);
4227}
4228
4230{
4232 rStrm.CopyRecordToStream( maDffStrm );
4233}
4234
4236{
4238 // store the new object in the internal containers
4239 maObjMap[ maDffStrm.Tell() ] = xDrawObj;
4240 maObjMapId[ xDrawObj->GetObjId() ] = xDrawObj;
4241}
4242
4244{
4245 XclImpObjTextRef xTextData = std::make_shared<XclImpObjTextData>();
4246 maTextMap[ maDffStrm.Tell() ] = xTextData;
4247
4248 // 1) read the TXO record
4249 xTextData->maData.ReadTxo8( rStrm );
4250
4251 // 2) first CONTINUE with string
4252 xTextData->mxString.reset();
4253 bool bValid = true;
4254 if( xTextData->maData.mnTextLen > 0 )
4255 {
4256 bValid = (rStrm.GetNextRecId() == EXC_ID_CONT) && rStrm.StartNextRecord();
4257 OSL_ENSURE( bValid, "XclImpDrawing::ReadTxo - missing CONTINUE record" );
4258 if( bValid )
4259 xTextData->mxString = std::make_shared<XclImpString>( rStrm.ReadUniString( xTextData->maData.mnTextLen ) );
4260 }
4261
4262 // 3) second CONTINUE with formatting runs
4263 if( xTextData->maData.mnFormatSize > 0 )
4264 {
4265 bValid = (rStrm.GetNextRecId() == EXC_ID_CONT) && rStrm.StartNextRecord();
4266 OSL_ENSURE( bValid, "XclImpDrawing::ReadTxo - missing CONTINUE record" );
4267 if( bValid )
4268 xTextData->ReadFormats( rStrm );
4269 }
4270}
4271
4273 XclImpDrawing( rRoot, true ),
4274 maScUsedArea( ScAddress::INITIALIZE_INVALID )
4275{
4276 maScUsedArea.aStart.SetTab( nScTab );
4277 maScUsedArea.aEnd.SetTab( nScTab );
4278}
4279
4281{
4282 switch( GetBiff() )
4283 {
4284 case EXC_BIFF2:
4285 case EXC_BIFF3:
4286 case EXC_BIFF4:
4287 case EXC_BIFF5:
4288 ReadNote3( rStrm );
4289 break;
4290 case EXC_BIFF8:
4291 ReadNote8( rStrm );
4292 break;
4293 default:
4295 }
4296}
4297
4299{
4301 auto xChartObj = std::make_shared<XclImpChartObj>( GetRoot(), true );
4302 xChartObj->ReadChartSubStream( rStrm );
4303 // insert the chart as raw object without connected DFF data
4304 AppendRawObject( xChartObj );
4305}
4306
4308{
4309 if( SdrModel* pSdrModel = GetDoc().GetDrawLayer() )
4310 if( SdrPage* pSdrPage = GetSdrPage( maScUsedArea.aStart.Tab() ) )
4311 ImplConvertObjects( rDffConv, *pSdrModel, *pSdrPage );
4312}
4313
4314tools::Rectangle XclImpSheetDrawing::CalcAnchorRect( const XclObjAnchor& rAnchor, bool /*bDffAnchor*/ ) const
4315{
4316 return rAnchor.GetRect( GetRoot(), maScUsedArea.aStart.Tab(), MapUnit::Map100thMM );
4317}
4318
4320{
4321 ScRange aScObjArea = rDrawObj.GetUsedArea( maScUsedArea.aStart.Tab() );
4322 if( aScObjArea.IsValid() )
4323 maScUsedArea.ExtendTo( aScObjArea );
4324}
4325
4326// private --------------------------------------------------------------------
4327
4329{
4330 XclAddress aXclPos;
4331 rStrm >> aXclPos;
4332 sal_uInt16 nTotalLen = rStrm.ReaduInt16();
4333
4334 ScAddress aScNotePos( ScAddress::UNINITIALIZED );
4335 if( !GetAddressConverter().ConvertAddress( aScNotePos, aXclPos, maScUsedArea.aStart.Tab(), true ) )
4336 return;
4337
4338 sal_uInt16 nPartLen = ::std::min( nTotalLen, static_cast< sal_uInt16 >( rStrm.GetRecLeft() ) );
4339 OUStringBuffer aNoteText(rStrm.ReadRawByteString( nPartLen ));
4340 nTotalLen = nTotalLen - nPartLen;
4341 while (true)
4342 {
4343 if (!nTotalLen)
4344 break;
4345 if (rStrm.GetNextRecId() != EXC_ID_NOTE)
4346 break;
4347 if (!rStrm.StartNextRecord())
4348 break;
4349 rStrm >> aXclPos;
4350 nPartLen = rStrm.ReaduInt16();
4351 OSL_ENSURE( aXclPos.mnRow == 0xFFFF, "XclImpObjectManager::ReadNote3 - missing continuation NOTE record" );
4352 if( aXclPos.mnRow == 0xFFFF )
4353 {
4354 OSL_ENSURE( nPartLen <= nTotalLen, "XclImpObjectManager::ReadNote3 - string too long" );
4355 aNoteText.append(rStrm.ReadRawByteString( nPartLen ));
4356 nTotalLen = nTotalLen - ::std::min( nTotalLen, nPartLen );
4357 }
4358 else
4359 {
4360 // seems to be a new note, record already started -> load the note
4362 ReadNote( rStrm );
4363 nTotalLen = 0;
4364 }
4365 }
4366 ScNoteUtil::CreateNoteFromString( GetDoc(), aScNotePos, aNoteText.makeStringAndClear(), false, false );
4367}
4368
4370{
4371 XclAddress aXclPos;
4372 sal_uInt16 nFlags, nObjId;
4373 rStrm >> aXclPos;
4374 nFlags = rStrm.ReaduInt16();
4375 nObjId = rStrm.ReaduInt16();
4376
4377 ScAddress aScNotePos( ScAddress::UNINITIALIZED );
4378 if( GetAddressConverter().ConvertAddress( aScNotePos, aXclPos, maScUsedArea.aStart.Tab(), true ) )
4379 if( nObjId != EXC_OBJ_INVALID_ID )
4380 if( XclImpNoteObj* pNoteObj = dynamic_cast< XclImpNoteObj* >( FindDrawObj( nObjId ).get() ) )
4381 pNoteObj->SetNoteData( aScNotePos, nFlags );
4382}
4383
4384// The object manager =========================================================
4385
4387 XclImpRoot( rRoot )
4388{
4389 maDefObjNames[ EXC_OBJTYPE_GROUP ] = "Group";
4390 maDefObjNames[ EXC_OBJTYPE_LINE ] = ScResId( STR_SHAPE_LINE );
4391 maDefObjNames[ EXC_OBJTYPE_RECTANGLE ] = ScResId( STR_SHAPE_RECTANGLE );
4392 maDefObjNames[ EXC_OBJTYPE_OVAL ] = ScResId( STR_SHAPE_OVAL );
4393 maDefObjNames[ EXC_OBJTYPE_ARC ] = "Arc";
4394 maDefObjNames[ EXC_OBJTYPE_CHART ] = "Chart";
4395 maDefObjNames[ EXC_OBJTYPE_TEXT ] = "Text";
4396 maDefObjNames[ EXC_OBJTYPE_BUTTON ] = ScResId( STR_FORM_BUTTON );
4397 maDefObjNames[ EXC_OBJTYPE_PICTURE ] = "Picture";
4398 maDefObjNames[ EXC_OBJTYPE_POLYGON ] = "Freeform";
4399 maDefObjNames[ EXC_OBJTYPE_CHECKBOX ] = ScResId( STR_FORM_CHECKBOX );
4400 maDefObjNames[ EXC_OBJTYPE_OPTIONBUTTON ] = ScResId( STR_FORM_OPTIONBUTTON );
4401 maDefObjNames[ EXC_OBJTYPE_EDIT ] = "Edit Box";
4402 maDefObjNames[ EXC_OBJTYPE_LABEL ] = ScResId( STR_FORM_LABEL );
4403 maDefObjNames[ EXC_OBJTYPE_DIALOG ] = "Dialog Frame";
4404 maDefObjNames[ EXC_OBJTYPE_SPIN ] = ScResId( STR_FORM_SPINNER );
4405 maDefObjNames[ EXC_OBJTYPE_SCROLLBAR ] = ScResId( STR_FORM_SCROLLBAR );
4406 maDefObjNames[ EXC_OBJTYPE_LISTBOX ] = ScResId( STR_FORM_LISTBOX );
4407 maDefObjNames[ EXC_OBJTYPE_GROUPBOX ] = ScResId( STR_FORM_GROUPBOX );
4408 maDefObjNames[ EXC_OBJTYPE_DROPDOWN ] = ScResId( STR_FORM_DROPDOWN );
4409 maDefObjNames[ EXC_OBJTYPE_NOTE ] = "Comment";
4410 maDefObjNames[ EXC_OBJTYPE_DRAWING ] = ScResId( STR_SHAPE_AUTOSHAPE );
4411}
4412
4414{
4415}
4416
4418{
4420 // Excel continues this record with MSODRAWINGGROUP and CONTINUE records, hmm.
4421 rStrm.ResetRecord( true, EXC_ID_MSODRAWINGGROUP );
4423 rStrm.CopyRecordToStream( maDggStrm );
4424}
4425
4427{
4428 XclImpSheetDrawingRef& rxDrawing = maSheetDrawings[ nScTab ];
4429 if( !rxDrawing )
4430 rxDrawing = std::make_shared<XclImpSheetDrawing>( GetRoot(), nScTab );
4431 return *rxDrawing;
4432}
4433
4435{
4436 // do nothing if the document does not contain a drawing layer
4437 if( !GetDoc().GetDrawLayer() )
4438 return;
4439
4440 // get total progress bar size for all sheet drawing managers
4441 std::size_t nProgressSize = std::accumulate(maSheetDrawings.begin(), maSheetDrawings.end(), std::size_t(0),
4442 [](const std::size_t& rSum, const XclImpSheetDrawingMap::value_type& rEntry) { return rSum + rEntry.second->GetProgressSize(); });
4443 // nothing to do if progress bar is zero (no objects present)
4444 if( nProgressSize == 0 )
4445 return;
4446
4447 XclImpDffConverter aDffConv( GetRoot(), maDggStrm );
4448 aDffConv.StartProgressBar( nProgressSize );
4449 for( auto& rEntry : maSheetDrawings )
4450 rEntry.second->ConvertObjects( aDffConv );
4451
4452 // #i112436# don't call ScChartListenerCollection::SetDirty here,
4453 // instead use InterpretDirtyCells in ScDocument::CalcAfterLoad.
4454}
4455
4457{
4458 OUString aDefName;
4459 DefObjNameMap::const_iterator aIt = maDefObjNames.find( rDrawObj.GetObjType() );
4460 if( aIt != maDefObjNames.end() )
4461 aDefName = aIt->second;
4462 return aDefName + " " + OUString::number(static_cast<sal_Int32>(rDrawObj.GetObjId()));
4463}
4464
4466{
4467 XclImpSheetDrawingMap::const_iterator aIt = maSheetDrawings.find( nScTab );
4468 if( aIt != maSheetDrawings.end() )
4469 return aIt->second->GetUsedArea();
4471}
4472
4473// DFF property set helper ====================================================
4474
4476 XclImpRoot( rRoot ),
4477 maDffConv( rRoot, maDummyStrm )
4478{
4479}
4480
4482{
4483 sal_uInt32 nPropSetSize;
4484
4485 rStrm.PushPosition();
4486 rStrm.Ignore( 4 );
4487 nPropSetSize = rStrm.ReaduInt32();
4488 rStrm.PopPosition();
4489
4490 mxMemStrm.reset( new SvMemoryStream );
4491 rStrm.CopyToStream( *mxMemStrm, 8 + nPropSetSize );
4493 maDffConv.ReadPropSet( *mxMemStrm, nullptr );
4494}
4495
4496sal_uInt32 XclImpDffPropSet::GetPropertyValue( sal_uInt16 nPropId ) const
4497{
4498 return maDffConv.GetPropertyValue( nPropId, 0 );
4499}
4500
4502{
4503 if( mxMemStrm )
4504 maDffConv.ApplyAttributes( *mxMemStrm, rItemSet );
4505}
4506
4508{
4509 rPropSet.Read( rStrm );
4510 return rStrm;
4511}
4512
4513/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int32 nLineWidth
sal_Int32 mnTop
sal_Int32 mnRight
sal_Int32 mnBottom
sal_Int32 mnLeft
css::uno::Reference< css::frame::XModel2 > mxModel
Bitmap GetBitmap(Color aTransparentReplaceColor) const
sal_uInt32 GetPropertyValue(sal_uInt32 nId, sal_uInt32 nDefault) const
bool IsProperty(sal_uInt32 nRecType) const
bool GetPropertyBool(sal_uInt32 nId) const
OUString GetPropertyString(sal_uInt32 nId, SvStream &rStrm) const
bool SeekToContent(sal_uInt32 nRecType, SvStream &rSt) const
void ReadPropSet(SvStream &rIn, SvxMSDffClientData *pClientData) const
void ApplyAttributes(SvStream &rIn, SfxItemSet &rSet) const
sal_uLong GetRecEndFilePos() const
bool SeekToEndOfRecord(SvStream &rIn) const
sal_uLong GetRecBegFilePos() const
bool SeekToBegOfRecord(SvStream &rIn) const
sal_uInt16 nRecType
bool SeekToContent(SvStream &rIn) const
GraphicType GetType() const
void SetOutlinerMode(OutlinerMode nNew)
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
@ UNINITIALIZED
Definition: address.hxx:220
SCTAB Tab() const
Definition: address.hxx:283
void IncCol(SCCOL nDelta=1)
Definition: address.hxx:316
bool IsValid() const
Definition: address.hxx:305
SCROW Row() const
Definition: address.hxx:274
void SetTab(SCTAB nTabP)
Definition: address.hxx:295
void IncRow(SCROW nDelta=1)
Definition: address.hxx:312
@ INITIALIZE_INVALID
Definition: address.hxx:221
SCCOL Col() const
Definition: address.hxx:279
static ScMacroInfo * GetMacroInfo(SdrObject *pObj, bool bCreate=false)
Definition: drwlayer.cxx:2913
static void SetCellAnchoredFromPosition(SdrObject &rObj, const ScDocument &rDoc, SCTAB nTab, bool bResizeWithCell)
Definition: drwlayer.cxx:2575
OUString GetCodeName(SCTAB nTab) const
Definition: scextopt.cxx:200
static ScPostIt * CreateNoteFromString(ScDocument &rDoc, const ScAddress &rPos, const OUString &rNoteText, bool bShown, bool bAlwaysCreateCaption, sal_uInt32 nPostItId=0)
Creates a cell note based on the passed string and inserts it into the document.
Definition: postit.cxx:924
static ScPostIt * CreateNoteFromObjectData(ScDocument &rDoc, const ScAddress &rPos, SfxItemSet &&oItemSet, const OUString &rStyleName, const OutlinerParaObject &rOutlinerObj, const tools::Rectangle &rCaptionRect, bool bShown)
Creates a cell note based on the passed caption object data.
Definition: postit.cxx:891
ScRange & front()
Definition: rangelst.hxx:92
bool empty() const
Definition: rangelst.hxx:88
ScAddress aEnd
Definition: address.hxx:498
void ExtendTo(const ScRange &rRange)
Definition: address.cxx:1562
bool IsValid() const
Definition: address.hxx:544
ScAddress aStart
Definition: address.hxx:497
static void FillApiAddress(css::table::CellAddress &rApiAddress, const ScAddress &rScAddress)
Definition: convuno.hxx:70
static void FillApiRange(css::table::CellRangeAddress &rApiRange, const ScRange &rScRange)
Definition: convuno.hxx:87
static css::uno::Reference< css::uno::XInterface > CreateInstance(const css::uno::Reference< css::lang::XMultiServiceFactory > &xFactory, const OUString &rServiceName)
Creates an instance from the passed service name, using the passed service factory.
A wrapper for a UNO property set.
Definition: fapihelper.hxx:104
void SetProperty(const OUString &rPropName, const Type &rValue)
Puts the passed value into the property set.
Definition: fapihelper.hxx:174
void SetStringProperty(const OUString &rPropName, const OUString &rValue)
Puts the passed string into the property set.
Definition: fapihelper.hxx:182
void SetBoolProperty(const OUString &rPropName, bool bValue)
Puts the passed Boolean value into the property set.
Definition: fapihelper.hxx:178
void SetPropertyValue(const css::beans::PropertyValue &rPropVal)
void EnableUndo(bool bEnable)
bool IsUndoEnabled() const
SdrObject * Next()
virtual void NbcInsertObject(SdrObject *pObj, size_t nPos=SAL_MAX_SIZE)
static SdrObject * getSdrObjectFromXShape(const css::uno::Reference< css::uno::XInterfa