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