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