xref: /AOO41X/main/sc/source/filter/xcl97/xcl97rec.cxx (revision b3f79822e811ac3493b185030a72c3c5a51f32d8)
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 <svx/svdpool.hxx>
28 #include <svx/sdtaitm.hxx>
29 #include <svx/svdotext.hxx>
30 #include <editeng/editobj.hxx>
31 #include <svx/svdoole2.hxx>
32 #include <sot/storage.hxx>
33 #include <svl/itemset.hxx>
34 #include <svx/svdpage.hxx>
35 #include <svx/svdocapt.hxx>
36 #include <svx/unoapi.hxx>
37 #include <editeng/writingmodeitem.hxx>
38 #include <vcl/svapp.hxx>
39 #include <rtl/math.hxx>
40 #include <svl/zformat.hxx>
41 #include "cell.hxx"
42 #include "drwlayer.hxx"
43 
44 #include "xcl97rec.hxx"
45 #include "xcl97esc.hxx"
46 #include "editutil.hxx"
47 #include "xecontent.hxx"
48 #include "xeescher.hxx"
49 #include "xestyle.hxx"
50 #include "xelink.hxx"
51 
52 #include "scitems.hxx"
53 
54 #include <unotools/fltrcfg.hxx>
55 #include <editeng/brshitem.hxx>
56 #include <editeng/boxitem.hxx>
57 #include <editeng/frmdiritem.hxx>
58 #include <editeng/adjitem.hxx>
59 #include <editeng/eeitem.hxx>
60 #include <filter/msfilter/msoleexp.hxx>
61 
62 #include <unotools/localedatawrapper.hxx>
63 
64 #include <stdio.h>
65 
66 #include "document.hxx"
67 #include "conditio.hxx"
68 #include "rangelst.hxx"
69 #include "stlpool.hxx"
70 #include "viewopti.hxx"
71 #include "scextopt.hxx"
72 #include "docoptio.hxx"
73 #include "patattr.hxx"
74 #include "tabprotection.hxx"
75 
76 using namespace ::oox;
77 
78 using ::rtl::OString;
79 using ::rtl::OUString;
80 using namespace ::com::sun::star;
81 using ::com::sun::star::uno::Reference;
82 using ::com::sun::star::uno::UNO_QUERY;
83 using ::com::sun::star::beans::XPropertySet;
84 using ::com::sun::star::drawing::XShape;
85 
86 // ============================================================================
87 
XclExpObjList(const XclExpRoot & rRoot,XclEscherEx & rEscherEx)88 XclExpObjList::XclExpObjList( const XclExpRoot& rRoot, XclEscherEx& rEscherEx ) :
89     XclExpRoot( rRoot ),
90     mrEscherEx( rEscherEx ),
91     pSolverContainer( 0 )
92 {
93     pMsodrawingPerSheet = new XclExpMsoDrawing( rEscherEx );
94     // open the DGCONTAINER and the patriarch group shape
95     mrEscherEx.OpenContainer( ESCHER_DgContainer );
96     Rectangle aRect( 0, 0, 0, 0 );
97     mrEscherEx.EnterGroup( &aRect );
98     mrEscherEx.UpdateDffFragmentEnd();
99 }
100 
~XclExpObjList()101 XclExpObjList::~XclExpObjList()
102 {
103     for ( XclObj* p = First(); p; p = Next() )
104         delete p;
105     delete pMsodrawingPerSheet;
106     delete pSolverContainer;
107 }
108 
Add(XclObj * pObj)109 sal_uInt16 XclExpObjList::Add( XclObj* pObj )
110 {
111     DBG_ASSERT( Count() < 0xFFFF, "XclExpObjList::Add: too much for Xcl" );
112     if ( Count() < 0xFFFF )
113     {
114         Insert( pObj, LIST_APPEND );
115         sal_uInt16 nCnt = (sal_uInt16) Count();
116         pObj->SetId( nCnt );
117         return nCnt;
118     }
119     else
120     {
121         delete pObj;
122         return 0;
123     }
124 }
125 
EndSheet()126 void XclExpObjList::EndSheet()
127 {
128     // Is there still something in the stream? -> The solver container
129     if( mrEscherEx.HasPendingDffData() )
130         pSolverContainer = new XclExpMsoDrawing( mrEscherEx );
131 
132     // close the DGCONTAINER created by XclExpObjList ctor MSODRAWING
133     mrEscherEx.CloseContainer();
134 }
135 
Save(XclExpStream & rStrm)136 void XclExpObjList::Save( XclExpStream& rStrm )
137 {
138     //! Escher must be written, even if there are no objects
139     pMsodrawingPerSheet->Save( rStrm );
140 
141     for ( XclObj* p = First(); p; p = Next() )
142         p->Save( rStrm );
143 
144     if( pSolverContainer )
145         pSolverContainer->Save( rStrm );
146 }
147 
148 // --- class XclObj --------------------------------------------------
149 
XclObj(XclExpObjectManager & rObjMgr,sal_uInt16 nObjType,bool bOwnEscher)150 XclObj::XclObj( XclExpObjectManager& rObjMgr, sal_uInt16 nObjType, bool bOwnEscher ) :
151     XclExpRecord( EXC_ID_OBJ, 26 ),
152     mrEscherEx( rObjMgr.GetEscherEx() ),
153     pClientTextbox( NULL ),
154     pTxo( NULL ),
155     mnObjType( nObjType ),
156     nObjId(0),
157     nGrbit( 0x6011 ),   // AutoLine, AutoFill, Printable, Locked
158     bFirstOnSheet( !rObjMgr.HasObj() ),
159     mbOwnEscher( bOwnEscher )
160 {
161     //! first object continues the first MSODRAWING record
162     if ( bFirstOnSheet )
163         pMsodrawing = rObjMgr.GetMsodrawingPerSheet();
164     else
165         pMsodrawing = new XclExpMsoDrawing( mrEscherEx );
166 }
167 
~XclObj()168 XclObj::~XclObj()
169 {
170     if ( !bFirstOnSheet )
171         delete pMsodrawing;
172     delete pClientTextbox;
173     delete pTxo;
174 }
175 
ImplWriteAnchor(const XclExpRoot &,const SdrObject * pSdrObj,const Rectangle * pChildAnchor)176 void XclObj::ImplWriteAnchor( const XclExpRoot& /*rRoot*/, const SdrObject* pSdrObj, const Rectangle* pChildAnchor )
177 {
178     if( pChildAnchor )
179     {
180         mrEscherEx.AddChildAnchor( *pChildAnchor );
181     }
182     else if( pSdrObj )
183     {
184         ::std::auto_ptr< XclExpDffAnchorBase > xDffAnchor( mrEscherEx.CreateDffAnchor( *pSdrObj ) );
185         xDffAnchor->WriteDffData( mrEscherEx );
186     }
187 }
188 
SetEscherShapeType(sal_uInt16 nType)189 void XclObj::SetEscherShapeType( sal_uInt16 nType )
190 {
191 //2do: what about the other defined ot... types?
192     switch ( nType )
193     {
194         case ESCHER_ShpInst_Line :
195             mnObjType = EXC_OBJTYPE_LINE;
196         break;
197         case ESCHER_ShpInst_Rectangle :
198         case ESCHER_ShpInst_RoundRectangle :
199             mnObjType = EXC_OBJTYPE_RECTANGLE;
200         break;
201         case ESCHER_ShpInst_Ellipse :
202             mnObjType = EXC_OBJTYPE_OVAL;
203         break;
204         case ESCHER_ShpInst_Arc :
205             mnObjType = EXC_OBJTYPE_ARC;
206         break;
207         case ESCHER_ShpInst_TextBox :
208             mnObjType = EXC_OBJTYPE_TEXT;
209         break;
210         case ESCHER_ShpInst_PictureFrame :
211             mnObjType = EXC_OBJTYPE_PICTURE;
212         break;
213         default:
214             mnObjType = EXC_OBJTYPE_DRAWING;
215     }
216 }
217 
SetText(const XclExpRoot & rRoot,const SdrTextObj & rObj)218 void XclObj::SetText( const XclExpRoot& rRoot, const SdrTextObj& rObj )
219 {
220     DBG_ASSERT( !pClientTextbox, "XclObj::SetText: already set" );
221     if ( !pClientTextbox )
222     {
223         mrEscherEx.UpdateDffFragmentEnd();
224         pClientTextbox = new XclExpMsoDrawing( mrEscherEx );
225         mrEscherEx.AddAtom( 0, ESCHER_ClientTextbox );    // TXO record
226         mrEscherEx.UpdateDffFragmentEnd();
227         pTxo = new XclTxo( rRoot, rObj );
228     }
229 }
230 
WriteBody(XclExpStream & rStrm)231 void XclObj::WriteBody( XclExpStream& rStrm )
232 {
233     DBG_ASSERT( mnObjType != EXC_OBJTYPE_UNKNOWN, "XclObj::WriteBody - unknown type" );
234 
235     // create a substream to be able to create subrecords
236     SvMemoryStream aMemStrm;
237     ::std::auto_ptr< XclExpStream > pXclStrm( new XclExpStream( aMemStrm, rStrm.GetRoot() ) );
238 
239     // write the ftCmo subrecord
240     pXclStrm->StartRecord( EXC_ID_OBJCMO, 18 );
241     *pXclStrm << mnObjType << nObjId << nGrbit;
242     pXclStrm->WriteZeroBytes( 12 );
243     pXclStrm->EndRecord();
244 
245     // write other subrecords
246     WriteSubRecs( *pXclStrm );
247 
248     // write the ftEnd subrecord
249     pXclStrm->StartRecord( EXC_ID_OBJEND, 0 );
250     pXclStrm->EndRecord();
251 
252     // copy the data to the OBJ record
253     pXclStrm.reset();
254     aMemStrm.Seek( 0 );
255     rStrm.CopyFromStream( aMemStrm );
256 }
257 
Save(XclExpStream & rStrm)258 void XclObj::Save( XclExpStream& rStrm )
259 {
260     // MSODRAWING record (msofbtSpContainer)
261     if ( !bFirstOnSheet )
262         pMsodrawing->Save( rStrm );
263 
264     // OBJ
265     XclExpRecord::Save( rStrm );
266 
267     // second MSODRAWING record and TXO and CONTINUE records
268     SaveTextRecs( rStrm );
269 }
270 
WriteSubRecs(XclExpStream &)271 void XclObj::WriteSubRecs( XclExpStream& /*rStrm*/ )
272 {
273 }
274 
SaveTextRecs(XclExpStream & rStrm)275 void XclObj::SaveTextRecs( XclExpStream& rStrm )
276 {
277     // MSODRAWING record (msofbtClientTextbox)
278     if ( pClientTextbox )
279         pClientTextbox->Save( rStrm );
280     // TXO and CONTINUE records
281     if ( pTxo )
282         pTxo->Save( rStrm );
283 }
284 
285 // --- class XclObjComment -------------------------------------------
286 
XclObjComment(XclExpObjectManager & rObjMgr,const Rectangle & rRect,const EditTextObject & rEditObj,SdrObject * pCaption,bool bVisible)287 XclObjComment::XclObjComment( XclExpObjectManager& rObjMgr, const Rectangle& rRect, const EditTextObject& rEditObj, SdrObject* pCaption, bool bVisible ) :
288     XclObj( rObjMgr, EXC_OBJTYPE_NOTE, true )
289 {
290     ProcessEscherObj( rObjMgr.GetRoot(), rRect, pCaption, bVisible);
291     // TXO
292     pTxo = new XclTxo( rObjMgr.GetRoot(), rEditObj, pCaption );
293 }
294 
ProcessEscherObj(const XclExpRoot & rRoot,const Rectangle & rRect,SdrObject * pCaption,const bool bVisible)295 void XclObjComment::ProcessEscherObj( const XclExpRoot& rRoot, const Rectangle& rRect, SdrObject* pCaption, const bool bVisible )
296 {
297     Reference<XShape> aXShape;
298     EscherPropertyContainer aPropOpt;
299 
300     if(pCaption)
301     {
302         aXShape = GetXShapeForSdrObject(pCaption);
303         Reference< XPropertySet > aXPropSet( aXShape, UNO_QUERY );
304         if( aXPropSet.is() )
305         {
306             aPropOpt.CreateFillProperties( aXPropSet,  sal_True);
307 
308             aPropOpt.AddOpt( ESCHER_Prop_lTxid, 0 );                        // undocumented
309         aPropOpt.AddOpt( 0x0158, 0x00000000 );                          // undocumented
310 
311             sal_uInt32 nValue = 0;
312             if(!aPropOpt.GetOpt( ESCHER_Prop_FitTextToShape, nValue ))
313                 aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x00080008 );      // bool field
314 
315             if(aPropOpt.GetOpt( ESCHER_Prop_fillColor, nValue ))
316             {
317                 // If the Colour is the same as the 'ToolTip' System colour then
318                 // use the default rather than the explicit colour value. This will
319                 // be incorrect where user has chosen to use this colour explicity.
320                 Color aColor = Color( (sal_uInt8)nValue, (sal_uInt8)( nValue >> 8 ), (sal_uInt8)( nValue >> 16 ) );
321                 const StyleSettings& rSett = Application::GetSettings().GetStyleSettings();
322                 if(aColor == rSett.GetHelpColor().GetColor())
323                 {
324                     aPropOpt.AddOpt( ESCHER_Prop_fillColor, 0x08000050 );
325                     aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x08000050 );
326                 }
327             }
328             else
329                 aPropOpt.AddOpt( ESCHER_Prop_fillColor, 0x08000050 );
330 
331             if(!aPropOpt.GetOpt( ESCHER_Prop_fillBackColor, nValue ))
332                 aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x08000050 );
333         if(!aPropOpt.GetOpt( ESCHER_Prop_fNoFillHitTest, nValue ))
334                 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x00110010 );      // bool field
335         if(!aPropOpt.GetOpt( ESCHER_Prop_shadowColor, nValue ))
336                 aPropOpt.AddOpt( ESCHER_Prop_shadowColor, 0x00000000 );
337         if(!aPropOpt.GetOpt( ESCHER_Prop_fshadowObscured, nValue ))     // bool field
338                 aPropOpt.AddOpt( ESCHER_Prop_fshadowObscured, 0x00030003 );     // bool field
339         }
340     }
341 
342     nGrbit = 0;     // all off: AutoLine, AutoFill, Printable, Locked
343     mrEscherEx.OpenContainer( ESCHER_SpContainer );
344     mrEscherEx.AddShape( ESCHER_ShpInst_TextBox, SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_HAVESPT );
345     sal_uInt32 nFlags = 0x000A0000;
346     ::set_flag( nFlags, sal_uInt32(2), !bVisible );
347     aPropOpt.AddOpt( ESCHER_Prop_fPrint, nFlags );                  // bool field
348     aPropOpt.Commit( mrEscherEx.GetStream() );
349 
350     XclExpDffNoteAnchor( rRoot, rRect ).WriteDffData( mrEscherEx );
351 
352     mrEscherEx.AddAtom( 0, ESCHER_ClientData );                        // OBJ record
353     mrEscherEx.UpdateDffFragmentEnd();
354 
355     //! Be sure to construct the MSODRAWING ClientTextbox record _after_ the
356     //! base OBJ's MSODRAWING record Escher data is completed.
357     pClientTextbox = new XclExpMsoDrawing( mrEscherEx );
358     mrEscherEx.AddAtom( 0, ESCHER_ClientTextbox );    // TXO record
359     mrEscherEx.UpdateDffFragmentEnd();
360     mrEscherEx.CloseContainer();   // ESCHER_SpContainer
361 }
362 
~XclObjComment()363 XclObjComment::~XclObjComment()
364 {
365 }
366 
Save(XclExpStream & rStrm)367 void XclObjComment::Save( XclExpStream& rStrm )
368 {
369     // content of this record
370     XclObj::Save( rStrm );
371 }
372 
373 // --- class XclObjDropDown ------------------------------------------
374 
XclObjDropDown(XclExpObjectManager & rObjMgr,const ScAddress & rPos,sal_Bool bFilt)375 XclObjDropDown::XclObjDropDown( XclExpObjectManager& rObjMgr, const ScAddress& rPos, sal_Bool bFilt ) :
376     XclObj( rObjMgr, EXC_OBJTYPE_DROPDOWN, true ),
377     bIsFiltered( bFilt )
378 {
379     SetLocked( sal_True );
380     SetPrintable( sal_False );
381     SetAutoFill( sal_True );
382     SetAutoLine( sal_False );
383     nGrbit |= 0x0100;   // undocumented
384     mrEscherEx.OpenContainer( ESCHER_SpContainer );
385     mrEscherEx.AddShape( ESCHER_ShpInst_HostControl, SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_HAVESPT );
386     EscherPropertyContainer aPropOpt;
387     aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x01040104 ); // bool field
388     aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x00080008 );      // bool field
389     aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x00010000 );      // bool field
390     aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080000 );     // bool field
391     aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x000A0000 );              // bool field
392     aPropOpt.Commit( mrEscherEx.GetStream() );
393 
394     XclExpDffDropDownAnchor( rObjMgr.GetRoot(), rPos ).WriteDffData( mrEscherEx );
395 
396     mrEscherEx.AddAtom( 0, ESCHER_ClientData );                        // OBJ record
397     mrEscherEx.UpdateDffFragmentEnd();
398     mrEscherEx.CloseContainer();   // ESCHER_SpContainer
399 
400     // old size + ftSbs + ftLbsData
401     AddRecSize( 24 + 20 );
402 }
403 
~XclObjDropDown()404 XclObjDropDown::~XclObjDropDown()
405 {
406 }
407 
WriteSubRecs(XclExpStream & rStrm)408 void XclObjDropDown::WriteSubRecs( XclExpStream& rStrm )
409 {
410     // ftSbs subrecord - Scroll bars (dummy)
411     rStrm.StartRecord( EXC_ID_OBJSBS, 20 );
412     rStrm.WriteZeroBytes( 20 );
413     rStrm.EndRecord();
414 
415     // ftLbsData subrecord - Listbox data
416     sal_uInt16 nDropDownFlags = 0;
417     ::insert_value( nDropDownFlags, EXC_OBJ_DROPDOWN_SIMPLE, 0, 2 );
418     ::set_flag( nDropDownFlags, EXC_OBJ_DROPDOWN_FILTERED, bIsFiltered );
419     rStrm.StartRecord( EXC_ID_OBJLBSDATA, 16 );
420     rStrm   << (sal_uInt32)0 << (sal_uInt16)0 << (sal_uInt16)0x0301 << (sal_uInt16)0
421             << nDropDownFlags << sal_uInt16( 20 ) << sal_uInt16( 130 );
422     rStrm.EndRecord();
423 }
424 
425 // --- class XclTxo --------------------------------------------------
426 
lcl_GetHorAlignFromItemSet(const SfxItemSet & rItemSet)427 sal_uInt8 lcl_GetHorAlignFromItemSet( const SfxItemSet& rItemSet )
428 {
429     sal_uInt8 nHorAlign = EXC_OBJ_HOR_LEFT;
430 
431     switch( static_cast< const SvxAdjustItem& >( rItemSet.Get( EE_PARA_JUST ) ).GetAdjust() )
432     {
433         case SVX_ADJUST_LEFT:   nHorAlign = EXC_OBJ_HOR_LEFT;      break;
434         case SVX_ADJUST_CENTER: nHorAlign = EXC_OBJ_HOR_CENTER;    break;
435         case SVX_ADJUST_RIGHT:  nHorAlign = EXC_OBJ_HOR_RIGHT;     break;
436         case SVX_ADJUST_BLOCK:  nHorAlign = EXC_OBJ_HOR_JUSTIFY;   break;
437         default:;
438     }
439     return nHorAlign;
440 }
441 
lcl_GetVerAlignFromItemSet(const SfxItemSet & rItemSet)442 sal_uInt8 lcl_GetVerAlignFromItemSet( const SfxItemSet& rItemSet )
443 {
444     sal_uInt8 nVerAlign = EXC_OBJ_VER_TOP;
445 
446     switch( static_cast< const SdrTextVertAdjustItem& >( rItemSet.Get( SDRATTR_TEXT_VERTADJUST ) ).GetValue() )
447     {
448         case SDRTEXTVERTADJUST_TOP:     nVerAlign = EXC_OBJ_VER_TOP;       break;
449         case SDRTEXTVERTADJUST_CENTER:  nVerAlign = EXC_OBJ_VER_CENTER;    break;
450         case SDRTEXTVERTADJUST_BOTTOM:  nVerAlign = EXC_OBJ_VER_BOTTOM;    break;
451         case SDRTEXTVERTADJUST_BLOCK:   nVerAlign = EXC_OBJ_VER_JUSTIFY;   break;
452     }
453     return nVerAlign;
454 }
455 
XclTxo(const String & rString,sal_uInt16 nFontIx)456 XclTxo::XclTxo( const String& rString, sal_uInt16 nFontIx ) :
457     mpString( new XclExpString( rString ) ),
458     mnRotation( EXC_OBJ_ORIENT_NONE ),
459     mnHorAlign( EXC_OBJ_HOR_LEFT ),
460     mnVerAlign( EXC_OBJ_VER_TOP )
461 {
462     if( mpString->Len() )
463     {
464         // If there is text, Excel *needs* the 2nd CONTINUE record with at least two format runs
465         mpString->AppendFormat( 0, nFontIx );
466         mpString->AppendFormat( mpString->Len(), EXC_FONT_APP );
467     }
468 }
469 
XclTxo(const XclExpRoot & rRoot,const SdrTextObj & rTextObj)470 XclTxo::XclTxo( const XclExpRoot& rRoot, const SdrTextObj& rTextObj ) :
471     mpString( XclExpStringHelper::CreateString( rRoot, rTextObj ) ),
472     mnRotation( EXC_OBJ_ORIENT_NONE ),
473     mnHorAlign( EXC_OBJ_HOR_LEFT ),
474     mnVerAlign( EXC_OBJ_VER_TOP )
475 {
476     // additional alignment and orientation items
477     const SfxItemSet& rItemSet = rTextObj.GetMergedItemSet();
478 
479     // horizontal alignment
480     SetHorAlign( lcl_GetHorAlignFromItemSet( rItemSet ) );
481 
482     // vertical alignment
483     SetVerAlign( lcl_GetVerAlignFromItemSet( rItemSet ) );
484 
485     // rotation
486     long nAngle = rTextObj.GetRotateAngle();
487     if( (4500 < nAngle) && (nAngle < 13500) )
488         mnRotation = EXC_OBJ_ORIENT_90CCW;
489     else if( (22500 < nAngle) && (nAngle < 31500) )
490         mnRotation = EXC_OBJ_ORIENT_90CW;
491     else
492         mnRotation = EXC_OBJ_ORIENT_NONE;
493 }
494 
XclTxo(const XclExpRoot & rRoot,const EditTextObject & rEditObj,SdrObject * pCaption)495 XclTxo::XclTxo( const XclExpRoot& rRoot, const EditTextObject& rEditObj, SdrObject* pCaption ) :
496     mpString( XclExpStringHelper::CreateString( rRoot, rEditObj ) ),
497     mnRotation( EXC_OBJ_ORIENT_NONE ),
498     mnHorAlign( EXC_OBJ_HOR_LEFT ),
499     mnVerAlign( EXC_OBJ_VER_TOP )
500 {
501     if(pCaption)
502     {
503         // Excel has one alignment per NoteObject while Calc supports
504         // one alignment per paragraph - use the first paragraph
505         // alignment (if set) as our overall alignment.
506         String aParaText( rEditObj.GetText( 0 ) );
507         if( aParaText.Len() )
508         {
509             SfxItemSet aSet( rEditObj.GetParaAttribs( 0));
510             const SfxPoolItem* pItem = NULL;
511             if( aSet.GetItemState( EE_PARA_JUST, sal_True, &pItem ) == SFX_ITEM_SET )
512             {
513                 SvxAdjust eEEAlign = static_cast< const SvxAdjustItem& >( *pItem ).GetAdjust();
514                 pCaption->SetMergedItem( SvxAdjustItem( eEEAlign, EE_PARA_JUST ) );
515             }
516         }
517         const SfxItemSet& rItemSet = pCaption->GetMergedItemSet();
518 
519         // horizontal alignment
520         SetHorAlign( lcl_GetHorAlignFromItemSet( rItemSet ) );
521 
522         // vertical alignment
523         SetVerAlign( lcl_GetVerAlignFromItemSet( rItemSet ) );
524 
525         // orientation alignment
526         const SvxWritingModeItem& rItem = static_cast< const SvxWritingModeItem& >( rItemSet.Get( SDRATTR_TEXTDIRECTION ) );
527         if( rItem.GetValue() == com::sun::star::text::WritingMode_TB_RL )
528             mnRotation = EXC_OBJ_ORIENT_90CW;
529     }
530 }
531 
SaveCont(XclExpStream & rStrm)532 void XclTxo::SaveCont( XclExpStream& rStrm )
533 {
534     DBG_ASSERT( mpString.get(), "XclTxo::SaveCont - missing string" );
535 
536     // #i96858# do not save existing string formatting if text is empty
537     sal_uInt16 nRunLen = mpString->IsEmpty() ? 0 : (8 * mpString->GetFormatsCount());
538     // alignment
539     sal_uInt16 nFlags = 0;
540     ::insert_value( nFlags, mnHorAlign, 1, 3 );
541     ::insert_value( nFlags, mnVerAlign, 4, 3 );
542 
543     rStrm << nFlags << mnRotation;
544     rStrm.WriteZeroBytes( 6 );
545     rStrm << mpString->Len() << nRunLen << sal_uInt32( 0 );
546 }
547 
Save(XclExpStream & rStrm)548 void XclTxo::Save( XclExpStream& rStrm )
549 {
550     // Write the TXO part
551     ExcRecord::Save( rStrm );
552 
553     // CONTINUE records are only written if there is some text
554     if( !mpString->IsEmpty() )
555     {
556         // CONTINUE for character array
557         rStrm.StartRecord( EXC_ID_CONT, mpString->GetBufferSize() + 1 );
558         rStrm << static_cast< sal_uInt8 >( mpString->GetFlagField() & EXC_STRF_16BIT ); // only Unicode flag
559         mpString->WriteBuffer( rStrm );
560         rStrm.EndRecord();
561 
562         // CONTINUE for formatting runs
563         rStrm.StartRecord( EXC_ID_CONT, 8 * mpString->GetFormatsCount() );
564         const XclFormatRunVec& rFormats = mpString->GetFormats();
565         for( XclFormatRunVec::const_iterator aIt = rFormats.begin(), aEnd = rFormats.end(); aIt != aEnd; ++aIt )
566             rStrm << aIt->mnChar << aIt->mnFontIdx << sal_uInt32( 0 );
567         rStrm.EndRecord();
568     }
569 }
570 
GetNum() const571 sal_uInt16 XclTxo::GetNum() const
572 {
573     return EXC_ID_TXO;
574 }
575 
GetLen() const576 sal_Size XclTxo::GetLen() const
577 {
578     return 18;
579 }
580 
581 // --- class XclObjOle -------------------------------------------
582 
XclObjOle(XclExpObjectManager & rObjMgr,const SdrObject & rObj)583 XclObjOle::XclObjOle( XclExpObjectManager& rObjMgr, const SdrObject& rObj ) :
584     XclObj( rObjMgr, EXC_OBJTYPE_PICTURE ),
585     rOleObj( rObj ),
586     pRootStorage( rObjMgr.GetRoot().GetRootStorage() )
587 {
588 }
589 
~XclObjOle()590 XclObjOle::~XclObjOle()
591 {
592 }
593 
WriteSubRecs(XclExpStream & rStrm)594 void XclObjOle::WriteSubRecs( XclExpStream& rStrm )
595 {
596     // write only as embedded, not linked
597     String          aStorageName( RTL_CONSTASCII_USTRINGPARAM( "MBD" ) );
598     sal_Char        aBuf[ sizeof(sal_uInt32) * 2 + 1 ];
599     // FIXME Eeek! Is this just a way to get a unique id?
600     sal_uInt32          nPictureId = sal_uInt32(sal_uIntPtr(this) >> 2);
601     sprintf( aBuf, "%08X", static_cast< unsigned int >( nPictureId ) );        // #100211# - checked
602     aStorageName.AppendAscii( aBuf );
603     SotStorageRef    xOleStg = pRootStorage->OpenSotStorage( aStorageName,
604                             STREAM_READWRITE| STREAM_SHARE_DENYALL );
605     if( xOleStg.Is() )
606     {
607         uno::Reference < embed::XEmbeddedObject > xObj( ((SdrOle2Obj&)rOleObj).GetObjRef() );
608         if ( xObj.is() )
609         {
610             // set version to "old" version, because it must be
611             // saved in MS notation.
612             sal_uInt32                  nFl = 0;
613             SvtFilterOptions*       pFltOpts = SvtFilterOptions::Get();
614             if( pFltOpts )
615             {
616                 if( pFltOpts->IsMath2MathType() )
617                     nFl |= OLE_STARMATH_2_MATHTYPE;
618 
619                 if( pFltOpts->IsWriter2WinWord() )
620                     nFl |= OLE_STARWRITER_2_WINWORD;
621 
622                 if( pFltOpts->IsCalc2Excel() )
623                     nFl |= OLE_STARCALC_2_EXCEL;
624 
625                 if( pFltOpts->IsImpress2PowerPoint() )
626                     nFl |= OLE_STARIMPRESS_2_POWERPOINT;
627             }
628 
629             SvxMSExportOLEObjects   aOLEExpFilt( nFl );
630             aOLEExpFilt.ExportOLEObject( xObj, *xOleStg );
631 
632             // OBJCF subrecord, undocumented as usual
633             rStrm.StartRecord( EXC_ID_OBJCF, 2 );
634             rStrm << sal_uInt16(0x0002);
635             rStrm.EndRecord();
636 
637             // OBJFLAGS subrecord, undocumented as usual
638             rStrm.StartRecord( EXC_ID_OBJFLAGS, 2 );
639             sal_uInt16 nFlags = EXC_OBJ_PIC_MANUALSIZE;
640             ::set_flag( nFlags, EXC_OBJ_PIC_SYMBOL, ((SdrOle2Obj&)rOleObj).GetAspect() == embed::Aspects::MSOLE_ICON );
641             rStrm << nFlags;
642             rStrm.EndRecord();
643 
644             // OBJPICTFMLA subrecord, undocumented as usual
645             XclExpString aName( xOleStg->GetUserName() );
646             sal_uInt16 nPadLen = (sal_uInt16)(aName.GetSize() & 0x01);
647             sal_uInt16 nFmlaLen = static_cast< sal_uInt16 >( 12 + aName.GetSize() + nPadLen );
648             sal_uInt16 nSubRecLen = nFmlaLen + 6;
649 
650             rStrm.StartRecord( EXC_ID_OBJPICTFMLA, nSubRecLen );
651             rStrm   << nFmlaLen
652                     << sal_uInt16( 5 ) << sal_uInt32( 0 ) << sal_uInt8( 2 )
653                     << sal_uInt32( 0 ) << sal_uInt8( 3 )
654                     << aName;
655             if( nPadLen )
656                 rStrm << sal_uInt8( 0 );       // pad byte
657             rStrm << nPictureId;
658             rStrm.EndRecord();
659         }
660     }
661 }
662 
Save(XclExpStream & rStrm)663 void XclObjOle::Save( XclExpStream& rStrm )
664 {
665     // content of this record
666     XclObj::Save( rStrm );
667 }
668 
669 // --- class XclObjAny -------------------------------------------
670 
XclObjAny(XclExpObjectManager & rObjMgr)671 XclObjAny::XclObjAny( XclExpObjectManager& rObjMgr ) :
672     XclObj( rObjMgr, EXC_OBJTYPE_UNKNOWN )
673 {
674 }
675 
~XclObjAny()676 XclObjAny::~XclObjAny()
677 {
678 }
679 
WriteSubRecs(XclExpStream & rStrm)680 void XclObjAny::WriteSubRecs( XclExpStream& rStrm )
681 {
682     if( mnObjType == EXC_OBJTYPE_GROUP )
683         // ftGmo subrecord
684         rStrm << EXC_ID_OBJGMO << sal_uInt16(2) << sal_uInt16(0);
685 }
686 
Save(XclExpStream & rStrm)687 void XclObjAny::Save( XclExpStream& rStrm )
688 {
689     if( mnObjType == EXC_OBJTYPE_GROUP )
690         // old size + ftGmo
691         AddRecSize( 6 );
692 
693     // content of this record
694     XclObj::Save( rStrm );
695 }
696 
697 // --- class ExcBof8_Base --------------------------------------------
698 
ExcBof8_Base()699 ExcBof8_Base::ExcBof8_Base()
700 {
701     nVers           = 0x0600;
702     nRupBuild       = 0x0dbb;
703     nRupYear        = 0x07cc;
704 //  nFileHistory    = 0x00000001;   // last edited by Microsoft Excel for Windows
705     nFileHistory    = 0x00000000;
706     nLowestBiffVer  = 0x00000006;   // Biff8
707 }
708 
709 
SaveCont(XclExpStream & rStrm)710 void ExcBof8_Base::SaveCont( XclExpStream& rStrm )
711 {
712     rStrm.DisableEncryption();
713     rStrm   << nVers << nDocType << nRupBuild << nRupYear
714             << nFileHistory << nLowestBiffVer;
715 }
716 
717 
GetNum() const718 sal_uInt16 ExcBof8_Base::GetNum() const
719 {
720     return 0x0809;
721 }
722 
723 
GetLen() const724 sal_Size ExcBof8_Base::GetLen() const
725 {
726     return 16;
727 }
728 
729 
730 // --- class ExcBof8 -------------------------------------------------
731 
ExcBof8()732 ExcBof8::ExcBof8()
733 {
734     nDocType = 0x0010;
735 }
736 
737 
738 // --- class ExcBofW8 ------------------------------------------------
739 
ExcBofW8()740 ExcBofW8::ExcBofW8()
741 {
742     nDocType = 0x0005;
743 }
744 
745 
746 // --- class ExcBundlesheet8 -----------------------------------------
747 
ExcBundlesheet8(RootData & rRootData,SCTAB _nTab)748 ExcBundlesheet8::ExcBundlesheet8( RootData& rRootData, SCTAB _nTab ) :
749     ExcBundlesheetBase( rRootData, static_cast<sal_uInt16>(_nTab) ),
750     sUnicodeName( rRootData.pER->GetTabInfo().GetScTabName( _nTab ) )
751 {
752 }
753 
754 
ExcBundlesheet8(const String & rString)755 ExcBundlesheet8::ExcBundlesheet8( const String& rString ) :
756     ExcBundlesheetBase(),
757     sUnicodeName( rString )
758 {
759 }
760 
761 
GetName() const762 XclExpString ExcBundlesheet8::GetName() const
763 {
764     return XclExpString( sUnicodeName, EXC_STR_8BITLENGTH );
765 }
766 
767 
SaveCont(XclExpStream & rStrm)768 void ExcBundlesheet8::SaveCont( XclExpStream& rStrm )
769 {
770     nOwnPos = rStrm.GetSvStreamPos();
771     // write dummy position, real position comes later
772     rStrm.DisableEncryption();
773     rStrm << sal_uInt32(0);
774     rStrm.EnableEncryption();
775     rStrm << nGrbit << GetName();
776 }
777 
778 
GetLen() const779 sal_Size ExcBundlesheet8::GetLen() const
780 {   // Text max 255 chars
781     return 8 + GetName().GetBufferSize();
782 }
783 
784 
SaveXml(XclExpXmlStream & rStrm)785 void ExcBundlesheet8::SaveXml( XclExpXmlStream& rStrm )
786 {
787     OUString sId;
788     rStrm.CreateOutputStream(
789             XclXmlUtils::GetStreamName( "xl/", "worksheets/sheet", nTab+1),
790             XclXmlUtils::GetStreamName( NULL, "worksheets/sheet", nTab+1),
791             rStrm.GetCurrentStream()->getOutputStream(),
792             "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
793             "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",
794             &sId );
795 
796     rStrm.GetCurrentStream()->singleElement( XML_sheet,
797             XML_name,               XclXmlUtils::ToOString( sUnicodeName ).getStr(),
798             XML_sheetId,            rtl::OString::valueOf( (sal_Int32)( nTab+1 ) ).getStr(),
799             XML_state,              nGrbit == 0x0000 ? "visible" : "hidden",
800             FSNS( XML_r, XML_id ),  XclXmlUtils::ToOString( sId ).getStr(),
801             FSEND );
802 }
803 
804 
805 
806 // --- class XclObproj -----------------------------------------------
807 
GetNum() const808 sal_uInt16 XclObproj::GetNum() const
809 {
810     return 0x00D3;
811 }
812 
813 
GetLen() const814 sal_Size XclObproj::GetLen() const
815 {
816     return 0;
817 }
818 
819 
820 // ---- class XclCodename --------------------------------------------
821 
XclCodename(const String & r)822 XclCodename::XclCodename( const String& r ) : aName( r )
823 {
824 }
825 
826 
SaveCont(XclExpStream & rStrm)827 void XclCodename::SaveCont( XclExpStream& rStrm )
828 {
829     rStrm << aName;
830 }
831 
832 
GetNum() const833 sal_uInt16 XclCodename::GetNum() const
834 {
835     return 0x01BA;
836 }
837 
838 
GetLen() const839 sal_Size XclCodename::GetLen() const
840 {
841     return aName.GetSize();
842 }
843 
844 
845 
846 // ---- Scenarios ----------------------------------------------------
847 
ExcEScenarioCell(sal_uInt16 nC,sal_uInt16 nR,const String & rTxt)848 ExcEScenarioCell::ExcEScenarioCell( sal_uInt16 nC, sal_uInt16 nR, const String& rTxt ) :
849         nCol( nC ),
850         nRow( nR ),
851         sText( rTxt, EXC_STR_DEFAULT, 255 )
852 {
853 }
854 
WriteAddress(XclExpStream & rStrm)855 void ExcEScenarioCell::WriteAddress( XclExpStream& rStrm )
856 {
857     rStrm << nRow << nCol;
858 }
859 
WriteText(XclExpStream & rStrm)860 void ExcEScenarioCell::WriteText( XclExpStream& rStrm )
861 {
862     rStrm << sText;
863 }
864 
SaveXml(XclExpXmlStream & rStrm)865 void ExcEScenarioCell::SaveXml( XclExpXmlStream& rStrm )
866 {
867     rStrm.GetCurrentStream()->singleElement( XML_inputCells,
868             // OOXTODO: XML_deleted,
869             // OOXTODO: XML_numFmtId,
870             XML_r,      XclXmlUtils::ToOString( ScAddress( nCol, nRow, 0 ) ).getStr(),
871             // OOXTODO: XML_undone,
872             XML_val,    XclXmlUtils::ToOString( sText ).getStr(),
873             FSEND );
874 }
875 
876 
877 
878 
ExcEScenario(const XclExpRoot & rRoot,SCTAB nTab)879 ExcEScenario::ExcEScenario( const XclExpRoot& rRoot, SCTAB nTab )
880 {
881     String  sTmpName;
882     String  sTmpComm;
883     Color   aDummyCol;
884     sal_uInt16  nFlags;
885 
886     ScDocument& rDoc = rRoot.GetDoc();
887     rDoc.GetName( nTab, sTmpName );
888     sName.Assign( sTmpName, EXC_STR_8BITLENGTH );
889     nRecLen = 8 + sName.GetBufferSize();
890 
891     rDoc.GetScenarioData( nTab, sTmpComm, aDummyCol, nFlags );
892     sComment.Assign( sTmpComm, EXC_STR_DEFAULT, 255 );
893     if( sComment.Len() )
894         nRecLen += sComment.GetSize();
895     nProtected = (nFlags & SC_SCENARIO_PROTECT) ? 1 : 0;
896 
897     sUserName.Assign( rRoot.GetUserName(), EXC_STR_DEFAULT, 255 );
898     nRecLen += sUserName.GetSize();
899 
900     const ScRangeList* pRList = rDoc.GetScenarioRanges( nTab );
901     if( !pRList )
902         return;
903 
904     sal_Bool    bContLoop = sal_True;
905     SCROW   nRow;
906     SCCOL   nCol;
907     String  sText;
908     double  fVal;
909 
910     for( sal_uInt32 nRange = 0; (nRange < pRList->Count()) && bContLoop; nRange++ )
911     {
912         const ScRange* pRange = pRList->GetObject( nRange );
913         for( nRow = pRange->aStart.Row(); (nRow <= pRange->aEnd.Row()) && bContLoop; nRow++ )
914             for( nCol = pRange->aStart.Col(); (nCol <= pRange->aEnd.Col()) && bContLoop; nCol++ )
915             {
916                 if( rDoc.HasValueData( nCol, nRow, nTab ) )
917                 {
918                     rDoc.GetValue( nCol, nRow, nTab, fVal );
919                     sText = ::rtl::math::doubleToUString( fVal,
920                             rtl_math_StringFormat_Automatic,
921                             rtl_math_DecimalPlaces_Max,
922                             ScGlobal::pLocaleData->getNumDecimalSep().GetChar(0),
923                             sal_True );
924                 }
925                 else
926                     rDoc.GetString( nCol, nRow, nTab, sText );
927                 bContLoop = Append( static_cast<sal_uInt16>(nCol),
928                         static_cast<sal_uInt16>(nRow), sText );
929             }
930     }
931 }
932 
~ExcEScenario()933 ExcEScenario::~ExcEScenario()
934 {
935     for( ExcEScenarioCell* pCell = _First(); pCell; pCell = _Next() )
936         delete pCell;
937 }
938 
Append(sal_uInt16 nCol,sal_uInt16 nRow,const String & rTxt)939 sal_Bool ExcEScenario::Append( sal_uInt16 nCol, sal_uInt16 nRow, const String& rTxt )
940 {
941     if( List::Count() == EXC_SCEN_MAXCELL )
942         return sal_False;
943 
944     ExcEScenarioCell* pCell = new ExcEScenarioCell( nCol, nRow, rTxt );
945     List::Insert( pCell, LIST_APPEND );
946     nRecLen += 6 + pCell->GetStringBytes();        // 4 bytes address, 2 bytes ifmt
947     return sal_True;
948 }
949 
SaveCont(XclExpStream & rStrm)950 void ExcEScenario::SaveCont( XclExpStream& rStrm )
951 {
952     rStrm   << (sal_uInt16) List::Count()       // number of cells
953             << nProtected                   // fProtection
954             << (sal_uInt8) 0                    // fHidden
955             << (sal_uInt8) sName.Len()          // length of scen name
956             << (sal_uInt8) sComment.Len()       // length of comment
957             << (sal_uInt8) sUserName.Len();     // length of user name
958     sName.WriteFlagField( rStrm );
959     sName.WriteBuffer( rStrm );
960 
961     rStrm << sUserName;
962 
963     if( sComment.Len() )
964         rStrm << sComment;
965 
966     ExcEScenarioCell* pCell;
967     for( pCell = _First(); pCell; pCell = _Next() )
968         pCell->WriteAddress( rStrm );           // pos of cell
969     for( pCell = _First(); pCell; pCell = _Next() )
970         pCell->WriteText( rStrm );              // string content
971     rStrm.SetSliceSize( 2 );
972     rStrm.WriteZeroBytes( 2 * List::Count() );  // date format
973 }
974 
GetNum() const975 sal_uInt16 ExcEScenario::GetNum() const
976 {
977     return 0x00AF;
978 }
979 
GetLen() const980 sal_Size ExcEScenario::GetLen() const
981 {
982     return nRecLen;
983 }
984 
SaveXml(XclExpXmlStream & rStrm)985 void ExcEScenario::SaveXml( XclExpXmlStream& rStrm )
986 {
987     sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
988     rWorkbook->startElement( XML_scenario,
989             XML_name,       XclXmlUtils::ToOString( sName ).getStr(),
990             XML_locked,     XclXmlUtils::ToPsz( nProtected ),
991             // OOXTODO: XML_hidden,
992             XML_count,      OString::valueOf( (sal_Int32) List::Count() ).getStr(),
993             XML_user,       XESTRING_TO_PSZ( sUserName ),
994             XML_comment,    XESTRING_TO_PSZ( sComment ),
995             FSEND );
996 
997     for( ExcEScenarioCell* pCell = _First(); pCell; pCell = _Next() )
998         pCell->SaveXml( rStrm );
999 
1000     rWorkbook->endElement( XML_scenario );
1001 }
1002 
1003 
1004 
1005 
ExcEScenarioManager(const XclExpRoot & rRoot,SCTAB nTab)1006 ExcEScenarioManager::ExcEScenarioManager( const XclExpRoot& rRoot, SCTAB nTab ) :
1007         nActive( 0 )
1008 {
1009     ScDocument& rDoc = rRoot.GetDoc();
1010     if( rDoc.IsScenario( nTab ) )
1011         return;
1012 
1013     SCTAB nFirstTab = nTab + 1;
1014     SCTAB nNewTab       = nFirstTab;
1015 
1016     while( rDoc.IsScenario( nNewTab ) )
1017     {
1018         Append( new ExcEScenario( rRoot, nNewTab ) );
1019 
1020         if( rDoc.IsActiveScenario( nNewTab ) )
1021             nActive = static_cast<sal_uInt16>(nNewTab - nFirstTab);
1022         nNewTab++;
1023     }
1024 }
1025 
~ExcEScenarioManager()1026 ExcEScenarioManager::~ExcEScenarioManager()
1027 {
1028     for( ExcEScenario* pScen = _First(); pScen; pScen = _Next() )
1029         delete pScen;
1030 }
1031 
SaveCont(XclExpStream & rStrm)1032 void ExcEScenarioManager::SaveCont( XclExpStream& rStrm )
1033 {
1034     rStrm   << (sal_uInt16) List::Count()       // number of scenarios
1035             << nActive                      // active scen
1036             << nActive                      // last displayed
1037             << (sal_uInt16) 0;                  // reference areas
1038 }
1039 
Save(XclExpStream & rStrm)1040 void ExcEScenarioManager::Save( XclExpStream& rStrm )
1041 {
1042     if( List::Count() )
1043         ExcRecord::Save( rStrm );
1044 
1045     for( ExcEScenario* pScen = _First(); pScen; pScen = _Next() )
1046         pScen->Save( rStrm );
1047 }
1048 
SaveXml(XclExpXmlStream & rStrm)1049 void ExcEScenarioManager::SaveXml( XclExpXmlStream& rStrm )
1050 {
1051     if( ! List::Count() )
1052         return;
1053 
1054     sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
1055     rWorkbook->startElement( XML_scenarios,
1056             XML_current,    OString::valueOf( (sal_Int32)nActive ).getStr(),
1057             XML_show,       OString::valueOf( (sal_Int32)nActive ).getStr(),
1058             // OOXTODO: XML_sqref,
1059             FSEND );
1060 
1061     for( ExcEScenario* pScen = _First(); pScen; pScen = _Next() )
1062         pScen->SaveXml( rStrm );
1063 
1064     rWorkbook->endElement( XML_scenarios );
1065 }
1066 
GetNum() const1067 sal_uInt16 ExcEScenarioManager::GetNum() const
1068 {
1069     return 0x00AE;
1070 }
1071 
GetLen() const1072 sal_Size ExcEScenarioManager::GetLen() const
1073 {
1074     return 8;
1075 }
1076 
1077 // ============================================================================
1078 
1079 struct XclExpTabProtectOption
1080 {
1081     ScTableProtection::Option   eOption;
1082     sal_uInt16                  nMask;
1083 };
1084 
XclExpSheetProtectOptions(const XclExpRoot & rRoot,SCTAB nTab)1085 XclExpSheetProtectOptions::XclExpSheetProtectOptions( const XclExpRoot& rRoot, SCTAB nTab ) :
1086     XclExpRecord( 0x0867, 23 )
1087 {
1088     static const XclExpTabProtectOption aTable[] =
1089     {
1090         { ScTableProtection::OBJECTS,               0x0001 },
1091         { ScTableProtection::SCENARIOS,             0x0002 },
1092         { ScTableProtection::FORMAT_CELLS,          0x0004 },
1093         { ScTableProtection::FORMAT_COLUMNS,        0x0008 },
1094         { ScTableProtection::FORMAT_ROWS,           0x0010 },
1095         { ScTableProtection::INSERT_COLUMNS,        0x0020 },
1096         { ScTableProtection::INSERT_ROWS,           0x0040 },
1097         { ScTableProtection::INSERT_HYPERLINKS,     0x0080 },
1098 
1099         { ScTableProtection::DELETE_COLUMNS,        0x0100 },
1100         { ScTableProtection::DELETE_ROWS,           0x0200 },
1101         { ScTableProtection::SELECT_LOCKED_CELLS,   0x0400 },
1102         { ScTableProtection::SORT,                  0x0800 },
1103         { ScTableProtection::AUTOFILTER,            0x1000 },
1104         { ScTableProtection::PIVOT_TABLES,          0x2000 },
1105         { ScTableProtection::SELECT_UNLOCKED_CELLS, 0x4000 },
1106 
1107         { ScTableProtection::NONE,                  0x0000 }
1108     };
1109 
1110     mnOptions = 0x0000;
1111     ScTableProtection* pProtect = rRoot.GetDoc().GetTabProtection(nTab);
1112     if (!pProtect)
1113         return;
1114 
1115     for (int i = 0; aTable[i].nMask != 0x0000; ++i)
1116     {
1117         if ( pProtect->isOptionEnabled(aTable[i].eOption) )
1118             mnOptions |= aTable[i].nMask;
1119     }
1120 }
1121 
WriteBody(XclExpStream & rStrm)1122 void XclExpSheetProtectOptions::WriteBody( XclExpStream& rStrm )
1123 {
1124     sal_uInt16 nBytes = 0x0867;
1125     rStrm << nBytes;
1126 
1127     sal_uChar nZero = 0x00;
1128     for (int i = 0; i < 9; ++i)
1129         rStrm << nZero;
1130 
1131     nBytes = 0x0200;
1132     rStrm << nBytes;
1133     nBytes = 0x0100;
1134     rStrm << nBytes;
1135     nBytes = 0xFFFF;
1136     rStrm << nBytes << nBytes;
1137 
1138     rStrm << mnOptions;
1139     nBytes = 0;
1140     rStrm << nBytes;
1141 }
1142 
1143 // ============================================================================
1144 
1145 
1146 
1147 
SaveCont(XclExpStream & rStrm)1148 void XclCalccount::SaveCont( XclExpStream& rStrm )
1149 {
1150     rStrm << nCount;
1151 }
1152 
1153 
XclCalccount(const ScDocument & rDoc)1154 XclCalccount::XclCalccount( const ScDocument& rDoc )
1155 {
1156     nCount = rDoc.GetDocOptions().GetIterCount();
1157 }
1158 
1159 
GetNum() const1160 sal_uInt16 XclCalccount::GetNum() const
1161 {
1162     return 0x000C;
1163 }
1164 
1165 
GetLen() const1166 sal_Size XclCalccount::GetLen() const
1167 {
1168     return 2;
1169 }
1170 
1171 
SaveXml(XclExpXmlStream & rStrm)1172 void XclCalccount::SaveXml( XclExpXmlStream& rStrm )
1173 {
1174     rStrm.WriteAttributes(
1175             XML_iterateCount, OString::valueOf( (sal_Int32)nCount ).getStr(),
1176             FSEND );
1177 }
1178 
1179 
1180 
1181 
SaveCont(XclExpStream & rStrm)1182 void XclIteration::SaveCont( XclExpStream& rStrm )
1183 {
1184     rStrm << nIter;
1185 }
1186 
1187 
XclIteration(const ScDocument & rDoc)1188 XclIteration::XclIteration( const ScDocument& rDoc )
1189 {
1190     nIter = rDoc.GetDocOptions().IsIter()? 1 : 0;
1191 }
1192 
1193 
GetNum() const1194 sal_uInt16 XclIteration::GetNum() const
1195 {
1196     return 0x0011;
1197 }
1198 
1199 
GetLen() const1200 sal_Size XclIteration::GetLen() const
1201 {
1202     return 2;
1203 }
1204 
1205 
SaveXml(XclExpXmlStream & rStrm)1206 void XclIteration::SaveXml( XclExpXmlStream& rStrm )
1207 {
1208     rStrm.WriteAttributes(
1209             XML_iterate, XclXmlUtils::ToPsz( nIter == 1 ),
1210             FSEND );
1211 }
1212 
1213 
1214 
1215 
SaveCont(XclExpStream & rStrm)1216 void XclDelta::SaveCont( XclExpStream& rStrm )
1217 {
1218     rStrm << fDelta;
1219 }
1220 
1221 
1222 
XclDelta(const ScDocument & rDoc)1223 XclDelta::XclDelta( const ScDocument& rDoc )
1224 {
1225     fDelta = rDoc.GetDocOptions().GetIterEps();
1226 }
1227 
1228 
GetNum() const1229 sal_uInt16 XclDelta::GetNum() const
1230 {
1231     return 0x0010;
1232 }
1233 
1234 
GetLen() const1235 sal_Size XclDelta::GetLen() const
1236 {
1237     return 8;
1238 }
1239 
1240 
SaveXml(XclExpXmlStream & rStrm)1241 void XclDelta::SaveXml( XclExpXmlStream& rStrm )
1242 {
1243     rStrm.WriteAttributes(
1244             XML_iterateDelta, OString::valueOf( fDelta ).getStr(),
1245             FSEND );
1246 }
1247 
1248 // ============================================================================
1249 
XclExpFileEncryption(const XclExpRoot & rRoot)1250 XclExpFileEncryption::XclExpFileEncryption( const XclExpRoot& rRoot ) :
1251     XclExpRecord(0x002F, 54),
1252     mrRoot(rRoot)
1253 {
1254 }
1255 
~XclExpFileEncryption()1256 XclExpFileEncryption::~XclExpFileEncryption()
1257 {
1258 }
1259 
WriteBody(XclExpStream & rStrm)1260 void XclExpFileEncryption::WriteBody( XclExpStream& rStrm )
1261 {
1262     // 0x0000 - neither standard nor strong encryption
1263     // 0x0001 - standard or strong encryption
1264     rStrm << static_cast<sal_uInt16>(0x0001);
1265 
1266     // 0x0000 - non standard encryption
1267     // 0x0001 - standard encryption
1268     sal_uInt16 nStdEnc = 0x0001;
1269     rStrm << nStdEnc << nStdEnc;
1270 
1271     sal_uInt8 pnDocId[16];
1272     sal_uInt8 pnSalt[16];
1273     sal_uInt8 pnSaltHash[16];
1274     XclExpEncrypterRef xEnc( new XclExpBiff8Encrypter(mrRoot) );
1275     xEnc->GetDocId(pnDocId);
1276     xEnc->GetSalt(pnSalt);
1277     xEnc->GetSaltDigest(pnSaltHash);
1278 
1279     rStrm.Write(pnDocId, 16);
1280     rStrm.Write(pnSalt, 16);
1281     rStrm.Write(pnSaltHash, 16);
1282 
1283     rStrm.SetEncrypter(xEnc);
1284 }
1285 
1286 // ============================================================================
1287 
XclExpInterfaceHdr(sal_uInt16 nCodePage)1288 XclExpInterfaceHdr::XclExpInterfaceHdr( sal_uInt16 nCodePage ) :
1289     XclExpUInt16Record( EXC_ID_INTERFACEHDR, nCodePage )
1290 {
1291 }
1292 
WriteBody(XclExpStream & rStrm)1293 void XclExpInterfaceHdr::WriteBody( XclExpStream& rStrm )
1294 {
1295     rStrm.DisableEncryption();
1296     rStrm << GetValue();
1297 }
1298 
1299 // ============================================================================
1300 
XclExpInterfaceEnd()1301 XclExpInterfaceEnd::XclExpInterfaceEnd() :
1302     XclExpRecord(0x00E2, 0) {}
1303 
~XclExpInterfaceEnd()1304 XclExpInterfaceEnd::~XclExpInterfaceEnd() {}
1305 
WriteBody(XclExpStream & rStrm)1306 void XclExpInterfaceEnd::WriteBody( XclExpStream& rStrm )
1307 {
1308     // Don't forget to re-enable encryption.
1309     rStrm.EnableEncryption();
1310 }
1311 
1312 // ============================================================================
1313 
XclExpWriteAccess()1314 XclExpWriteAccess::XclExpWriteAccess() :
1315     XclExpRecord(0x005C, 112)
1316 {
1317 }
1318 
~XclExpWriteAccess()1319 XclExpWriteAccess::~XclExpWriteAccess()
1320 {
1321 }
1322 
WriteBody(XclExpStream & rStrm)1323 void XclExpWriteAccess::WriteBody( XclExpStream& rStrm )
1324 {
1325     static const sal_uInt8 aData[] = {
1326         0x04, 0x00, 0x00,  'C',  'a',  'l',  'c', 0x20,
1327         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1328         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1329         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1330         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1331         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1332         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1333         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1334         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1335         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1336         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1337         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1338         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1339         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
1340 
1341     sal_Size nDataSize = sizeof(aData);
1342     for (sal_Size i = 0; i < nDataSize; ++i)
1343         rStrm << aData[i];
1344 }
1345 
1346 // ============================================================================
1347 
XclExpFileSharing(const XclExpRoot & rRoot,sal_uInt16 nPasswordHash,bool bRecommendReadOnly)1348 XclExpFileSharing::XclExpFileSharing( const XclExpRoot& rRoot, sal_uInt16 nPasswordHash, bool bRecommendReadOnly ) :
1349     XclExpRecord( EXC_ID_FILESHARING ),
1350     mnPasswordHash( nPasswordHash ),
1351     mbRecommendReadOnly( bRecommendReadOnly )
1352 {
1353     if( rRoot.GetBiff() <= EXC_BIFF5 )
1354         maUserName.AssignByte( rRoot.GetUserName(), rRoot.GetTextEncoding(), EXC_STR_8BITLENGTH );
1355     else
1356         maUserName.Assign( rRoot.GetUserName() );
1357 }
1358 
Save(XclExpStream & rStrm)1359 void XclExpFileSharing::Save( XclExpStream& rStrm )
1360 {
1361     if( (mnPasswordHash != 0) || mbRecommendReadOnly )
1362         XclExpRecord::Save( rStrm );
1363 }
1364 
WriteBody(XclExpStream & rStrm)1365 void XclExpFileSharing::WriteBody( XclExpStream& rStrm )
1366 {
1367     rStrm << sal_uInt16( mbRecommendReadOnly ? 1 : 0 ) << mnPasswordHash << maUserName;
1368 }
1369 
1370 // ============================================================================
1371 
XclExpProt4Rev()1372 XclExpProt4Rev::XclExpProt4Rev() :
1373     XclExpRecord(0x01AF, 2)
1374 {
1375 }
1376 
~XclExpProt4Rev()1377 XclExpProt4Rev::~XclExpProt4Rev()
1378 {
1379 }
1380 
WriteBody(XclExpStream & rStrm)1381 void XclExpProt4Rev::WriteBody( XclExpStream& rStrm )
1382 {
1383     rStrm << static_cast<sal_uInt16>(0x0000);
1384 }
1385 
1386 // ============================================================================
1387 
XclExpProt4RevPass()1388 XclExpProt4RevPass::XclExpProt4RevPass() :
1389     XclExpRecord(0x01BC, 2)
1390 {
1391 }
1392 
~XclExpProt4RevPass()1393 XclExpProt4RevPass::~XclExpProt4RevPass()
1394 {
1395 }
1396 
WriteBody(XclExpStream & rStrm)1397 void XclExpProt4RevPass::WriteBody( XclExpStream& rStrm )
1398 {
1399     rStrm << static_cast<sal_uInt16>(0x0000);
1400 }
1401 
1402 // ============================================================================
1403 
1404 static const sal_uInt8 nDataRecalcId[] = {
1405     0xC1, 0x01, 0x00, 0x00, 0x54, 0x8D, 0x01, 0x00
1406 };
1407 
XclExpRecalcId()1408 XclExpRecalcId::XclExpRecalcId() :
1409     XclExpDummyRecord(0x01C1, nDataRecalcId, sizeof(nDataRecalcId))
1410 {
1411 }
1412 
1413 // ============================================================================
1414 
1415 static const sal_uInt8 nDataBookExt[] = {
1416     0x63, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1417     0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1418     0x02
1419 };
1420 
XclExpBookExt()1421 XclExpBookExt::XclExpBookExt() :
1422     XclExpDummyRecord(0x0863, nDataBookExt, sizeof(nDataBookExt))
1423 {
1424 }
1425 
1426 // ============================================================================
1427 
XclRefmode(const ScDocument & rDoc)1428 XclRefmode::XclRefmode( const ScDocument& rDoc ) :
1429     XclExpBoolRecord( 0x000F, rDoc.GetAddressConvention() != formula::FormulaGrammar::CONV_XL_R1C1 )
1430 {
1431 }
1432 
SaveXml(XclExpXmlStream & rStrm)1433 void XclRefmode::SaveXml( XclExpXmlStream& rStrm )
1434 {
1435     rStrm.WriteAttributes(
1436             XML_refMode, GetBool() ? "A1" : "R1C1",
1437             FSEND );
1438 }
1439 
1440