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