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_scfilt.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