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