xref: /aoo4110/main/sc/source/filter/xcl97/xcl97rec.cxx (revision b1cdbd2c)
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