blob: d5f152fef8b88a582df9d35309c98ea54af24ab7 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
#include <svx/svdpool.hxx>
#include <svx/sdtaitm.hxx>
#include <svx/svdotext.hxx>
#include <editeng/editobj.hxx>
#include <svx/svdoole2.hxx>
#include <sot/storage.hxx>
#include <svl/itemset.hxx>
#include <svx/svdpage.hxx>
#include <svx/svdocapt.hxx>
#include <svx/unoapi.hxx>
#include <editeng/writingmodeitem.hxx>
#include <vcl/svapp.hxx>
#include <rtl/math.hxx>
#include <svl/zformat.hxx>
#include "cell.hxx"
#include "drwlayer.hxx"
#include "xcl97rec.hxx"
#include "xcl97esc.hxx"
#include "editutil.hxx"
#include "xecontent.hxx"
#include "xeescher.hxx"
#include "xestyle.hxx"
#include "xelink.hxx"
#include "scitems.hxx"
#include <unotools/fltrcfg.hxx>
#include <editeng/brshitem.hxx>
#include <editeng/boxitem.hxx>
#include <editeng/frmdiritem.hxx>
#include <editeng/adjitem.hxx>
#include <editeng/eeitem.hxx>
#include <filter/msfilter/msoleexp.hxx>
#include <unotools/localedatawrapper.hxx>
#include <stdio.h>
#include "document.hxx"
#include "conditio.hxx"
#include "rangelst.hxx"
#include "stlpool.hxx"
#include "viewopti.hxx"
#include "scextopt.hxx"
#include "docoptio.hxx"
#include "patattr.hxx"
#include "tabprotection.hxx"
using namespace ::oox;
using ::rtl::OString;
using ::rtl::OUString;
using namespace ::com::sun::star;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::drawing::XShape;
// ============================================================================
XclExpObjList::XclExpObjList( const XclExpRoot& rRoot, XclEscherEx& rEscherEx ) :
XclExpRoot( rRoot ),
mrEscherEx( rEscherEx ),
pSolverContainer( 0 )
{
pMsodrawingPerSheet = new XclExpMsoDrawing( rEscherEx );
// open the DGCONTAINER and the patriarch group shape
mrEscherEx.OpenContainer( ESCHER_DgContainer );
Rectangle aRect( 0, 0, 0, 0 );
mrEscherEx.EnterGroup( &aRect );
mrEscherEx.UpdateDffFragmentEnd();
}
XclExpObjList::~XclExpObjList()
{
for ( XclObj* p = First(); p; p = Next() )
delete p;
delete pMsodrawingPerSheet;
delete pSolverContainer;
}
sal_uInt16 XclExpObjList::Add( XclObj* pObj )
{
DBG_ASSERT( Count() < 0xFFFF, "XclExpObjList::Add: too much for Xcl" );
if ( Count() < 0xFFFF )
{
Insert( pObj, LIST_APPEND );
sal_uInt16 nCnt = (sal_uInt16) Count();
pObj->SetId( nCnt );
return nCnt;
}
else
{
delete pObj;
return 0;
}
}
void XclExpObjList::EndSheet()
{
// Is there still something in the stream? -> The solver container
if( mrEscherEx.HasPendingDffData() )
pSolverContainer = new XclExpMsoDrawing( mrEscherEx );
// close the DGCONTAINER created by XclExpObjList ctor MSODRAWING
mrEscherEx.CloseContainer();
}
void XclExpObjList::Save( XclExpStream& rStrm )
{
//! Escher must be written, even if there are no objects
pMsodrawingPerSheet->Save( rStrm );
for ( XclObj* p = First(); p; p = Next() )
p->Save( rStrm );
if( pSolverContainer )
pSolverContainer->Save( rStrm );
}
// --- class XclObj --------------------------------------------------
XclObj::XclObj( XclExpObjectManager& rObjMgr, sal_uInt16 nObjType, bool bOwnEscher ) :
XclExpRecord( EXC_ID_OBJ, 26 ),
mrEscherEx( rObjMgr.GetEscherEx() ),
pClientTextbox( NULL ),
pTxo( NULL ),
mnObjType( nObjType ),
nObjId(0),
nGrbit( 0x6011 ), // AutoLine, AutoFill, Printable, Locked
bFirstOnSheet( !rObjMgr.HasObj() ),
mbOwnEscher( bOwnEscher )
{
//! first object continues the first MSODRAWING record
if ( bFirstOnSheet )
pMsodrawing = rObjMgr.GetMsodrawingPerSheet();
else
pMsodrawing = new XclExpMsoDrawing( mrEscherEx );
}
XclObj::~XclObj()
{
if ( !bFirstOnSheet )
delete pMsodrawing;
delete pClientTextbox;
delete pTxo;
}
void XclObj::ImplWriteAnchor( const XclExpRoot& /*rRoot*/, const SdrObject* pSdrObj, const Rectangle* pChildAnchor )
{
if( pChildAnchor )
{
mrEscherEx.AddChildAnchor( *pChildAnchor );
}
else if( pSdrObj )
{
::std::auto_ptr< XclExpDffAnchorBase > xDffAnchor( mrEscherEx.CreateDffAnchor( *pSdrObj ) );
xDffAnchor->WriteDffData( mrEscherEx );
}
}
void XclObj::SetEscherShapeType( sal_uInt16 nType )
{
//2do: what about the other defined ot... types?
switch ( nType )
{
case ESCHER_ShpInst_Line :
mnObjType = EXC_OBJTYPE_LINE;
break;
case ESCHER_ShpInst_Rectangle :
case ESCHER_ShpInst_RoundRectangle :
mnObjType = EXC_OBJTYPE_RECTANGLE;
break;
case ESCHER_ShpInst_Ellipse :
mnObjType = EXC_OBJTYPE_OVAL;
break;
case ESCHER_ShpInst_Arc :
mnObjType = EXC_OBJTYPE_ARC;
break;
case ESCHER_ShpInst_TextBox :
mnObjType = EXC_OBJTYPE_TEXT;
break;
case ESCHER_ShpInst_PictureFrame :
mnObjType = EXC_OBJTYPE_PICTURE;
break;
default:
mnObjType = EXC_OBJTYPE_DRAWING;
}
}
void XclObj::SetText( const XclExpRoot& rRoot, const SdrTextObj& rObj )
{
DBG_ASSERT( !pClientTextbox, "XclObj::SetText: already set" );
if ( !pClientTextbox )
{
mrEscherEx.UpdateDffFragmentEnd();
pClientTextbox = new XclExpMsoDrawing( mrEscherEx );
mrEscherEx.AddAtom( 0, ESCHER_ClientTextbox ); // TXO record
mrEscherEx.UpdateDffFragmentEnd();
pTxo = new XclTxo( rRoot, rObj );
}
}
void XclObj::WriteBody( XclExpStream& rStrm )
{
DBG_ASSERT( mnObjType != EXC_OBJTYPE_UNKNOWN, "XclObj::WriteBody - unknown type" );
// create a substream to be able to create subrecords
SvMemoryStream aMemStrm;
::std::auto_ptr< XclExpStream > pXclStrm( new XclExpStream( aMemStrm, rStrm.GetRoot() ) );
// write the ftCmo subrecord
pXclStrm->StartRecord( EXC_ID_OBJCMO, 18 );
*pXclStrm << mnObjType << nObjId << nGrbit;
pXclStrm->WriteZeroBytes( 12 );
pXclStrm->EndRecord();
// write other subrecords
WriteSubRecs( *pXclStrm );
// write the ftEnd subrecord
pXclStrm->StartRecord( EXC_ID_OBJEND, 0 );
pXclStrm->EndRecord();
// copy the data to the OBJ record
pXclStrm.reset();
aMemStrm.Seek( 0 );
rStrm.CopyFromStream( aMemStrm );
}
void XclObj::Save( XclExpStream& rStrm )
{
// MSODRAWING record (msofbtSpContainer)
if ( !bFirstOnSheet )
pMsodrawing->Save( rStrm );
// OBJ
XclExpRecord::Save( rStrm );
// second MSODRAWING record and TXO and CONTINUE records
SaveTextRecs( rStrm );
}
void XclObj::WriteSubRecs( XclExpStream& /*rStrm*/ )
{
}
void XclObj::SaveTextRecs( XclExpStream& rStrm )
{
// MSODRAWING record (msofbtClientTextbox)
if ( pClientTextbox )
pClientTextbox->Save( rStrm );
// TXO and CONTINUE records
if ( pTxo )
pTxo->Save( rStrm );
}
// --- class XclObjComment -------------------------------------------
XclObjComment::XclObjComment( XclExpObjectManager& rObjMgr, const Rectangle& rRect, const EditTextObject& rEditObj, SdrObject* pCaption, bool bVisible ) :
XclObj( rObjMgr, EXC_OBJTYPE_NOTE, true )
{
ProcessEscherObj( rObjMgr.GetRoot(), rRect, pCaption, bVisible);
// TXO
pTxo = new XclTxo( rObjMgr.GetRoot(), rEditObj, pCaption );
}
void XclObjComment::ProcessEscherObj( const XclExpRoot& rRoot, const Rectangle& rRect, SdrObject* pCaption, const bool bVisible )
{
Reference<XShape> aXShape;
EscherPropertyContainer aPropOpt;
if(pCaption)
{
aXShape = GetXShapeForSdrObject(pCaption);
Reference< XPropertySet > aXPropSet( aXShape, UNO_QUERY );
if( aXPropSet.is() )
{
aPropOpt.CreateFillProperties( aXPropSet, sal_True);
aPropOpt.AddOpt( ESCHER_Prop_lTxid, 0 ); // undocumented
aPropOpt.AddOpt( 0x0158, 0x00000000 ); // undocumented
sal_uInt32 nValue = 0;
if(!aPropOpt.GetOpt( ESCHER_Prop_FitTextToShape, nValue ))
aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x00080008 ); // bool field
if(aPropOpt.GetOpt( ESCHER_Prop_fillColor, nValue ))
{
// If the Colour is the same as the 'ToolTip' System colour then
// use the default rather than the explicit colour value. This will
// be incorrect where user has chosen to use this colour explicity.
Color aColor = Color( (sal_uInt8)nValue, (sal_uInt8)( nValue >> 8 ), (sal_uInt8)( nValue >> 16 ) );
const StyleSettings& rSett = Application::GetSettings().GetStyleSettings();
if(aColor == rSett.GetHelpColor().GetColor())
{
aPropOpt.AddOpt( ESCHER_Prop_fillColor, 0x08000050 );
aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x08000050 );
}
}
else
aPropOpt.AddOpt( ESCHER_Prop_fillColor, 0x08000050 );
if(!aPropOpt.GetOpt( ESCHER_Prop_fillBackColor, nValue ))
aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x08000050 );
if(!aPropOpt.GetOpt( ESCHER_Prop_fNoFillHitTest, nValue ))
aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x00110010 ); // bool field
if(!aPropOpt.GetOpt( ESCHER_Prop_shadowColor, nValue ))
aPropOpt.AddOpt( ESCHER_Prop_shadowColor, 0x00000000 );
if(!aPropOpt.GetOpt( ESCHER_Prop_fshadowObscured, nValue )) // bool field
aPropOpt.AddOpt( ESCHER_Prop_fshadowObscured, 0x00030003 ); // bool field
}
}
nGrbit = 0; // all off: AutoLine, AutoFill, Printable, Locked
mrEscherEx.OpenContainer( ESCHER_SpContainer );
mrEscherEx.AddShape( ESCHER_ShpInst_TextBox, SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_HAVESPT );
sal_uInt32 nFlags = 0x000A0000;
::set_flag( nFlags, sal_uInt32(2), !bVisible );
aPropOpt.AddOpt( ESCHER_Prop_fPrint, nFlags ); // bool field
aPropOpt.Commit( mrEscherEx.GetStream() );
XclExpDffNoteAnchor( rRoot, rRect ).WriteDffData( mrEscherEx );
mrEscherEx.AddAtom( 0, ESCHER_ClientData ); // OBJ record
mrEscherEx.UpdateDffFragmentEnd();
//! Be sure to construct the MSODRAWING ClientTextbox record _after_ the
//! base OBJ's MSODRAWING record Escher data is completed.
pClientTextbox = new XclExpMsoDrawing( mrEscherEx );
mrEscherEx.AddAtom( 0, ESCHER_ClientTextbox ); // TXO record
mrEscherEx.UpdateDffFragmentEnd();
mrEscherEx.CloseContainer(); // ESCHER_SpContainer
}
XclObjComment::~XclObjComment()
{
}
void XclObjComment::Save( XclExpStream& rStrm )
{
// content of this record
XclObj::Save( rStrm );
}
// --- class XclObjDropDown ------------------------------------------
XclObjDropDown::XclObjDropDown( XclExpObjectManager& rObjMgr, const ScAddress& rPos, sal_Bool bFilt ) :
XclObj( rObjMgr, EXC_OBJTYPE_DROPDOWN, true ),
bIsFiltered( bFilt )
{
SetLocked( sal_True );
SetPrintable( sal_False );
SetAutoFill( sal_True );
SetAutoLine( sal_False );
nGrbit |= 0x0100; // undocumented
mrEscherEx.OpenContainer( ESCHER_SpContainer );
mrEscherEx.AddShape( ESCHER_ShpInst_HostControl, SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_HAVESPT );
EscherPropertyContainer aPropOpt;
aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x01040104 ); // bool field
aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x00080008 ); // bool field
aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x00010000 ); // bool field
aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080000 ); // bool field
aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x000A0000 ); // bool field
aPropOpt.Commit( mrEscherEx.GetStream() );
XclExpDffDropDownAnchor( rObjMgr.GetRoot(), rPos ).WriteDffData( mrEscherEx );
mrEscherEx.AddAtom( 0, ESCHER_ClientData ); // OBJ record
mrEscherEx.UpdateDffFragmentEnd();
mrEscherEx.CloseContainer(); // ESCHER_SpContainer
// old size + ftSbs + ftLbsData
AddRecSize( 24 + 20 );
}
XclObjDropDown::~XclObjDropDown()
{
}
void XclObjDropDown::WriteSubRecs( XclExpStream& rStrm )
{
// ftSbs subrecord - Scroll bars (dummy)
rStrm.StartRecord( EXC_ID_OBJSBS, 20 );
rStrm.WriteZeroBytes( 20 );
rStrm.EndRecord();
// ftLbsData subrecord - Listbox data
sal_uInt16 nDropDownFlags = 0;
::insert_value( nDropDownFlags, EXC_OBJ_DROPDOWN_SIMPLE, 0, 2 );
::set_flag( nDropDownFlags, EXC_OBJ_DROPDOWN_FILTERED, bIsFiltered );
rStrm.StartRecord( EXC_ID_OBJLBSDATA, 16 );
rStrm << (sal_uInt32)0 << (sal_uInt16)0 << (sal_uInt16)0x0301 << (sal_uInt16)0
<< nDropDownFlags << sal_uInt16( 20 ) << sal_uInt16( 130 );
rStrm.EndRecord();
}
// --- class XclTxo --------------------------------------------------
sal_uInt8 lcl_GetHorAlignFromItemSet( const SfxItemSet& rItemSet )
{
sal_uInt8 nHorAlign = EXC_OBJ_HOR_LEFT;
switch( static_cast< const SvxAdjustItem& >( rItemSet.Get( EE_PARA_JUST ) ).GetAdjust() )
{
case SVX_ADJUST_LEFT: nHorAlign = EXC_OBJ_HOR_LEFT; break;
case SVX_ADJUST_CENTER: nHorAlign = EXC_OBJ_HOR_CENTER; break;
case SVX_ADJUST_RIGHT: nHorAlign = EXC_OBJ_HOR_RIGHT; break;
case SVX_ADJUST_BLOCK: nHorAlign = EXC_OBJ_HOR_JUSTIFY; break;
default:;
}
return nHorAlign;
}
sal_uInt8 lcl_GetVerAlignFromItemSet( const SfxItemSet& rItemSet )
{
sal_uInt8 nVerAlign = EXC_OBJ_VER_TOP;
switch( static_cast< const SdrTextVertAdjustItem& >( rItemSet.Get( SDRATTR_TEXT_VERTADJUST ) ).GetValue() )
{
case SDRTEXTVERTADJUST_TOP: nVerAlign = EXC_OBJ_VER_TOP; break;
case SDRTEXTVERTADJUST_CENTER: nVerAlign = EXC_OBJ_VER_CENTER; break;
case SDRTEXTVERTADJUST_BOTTOM: nVerAlign = EXC_OBJ_VER_BOTTOM; break;
case SDRTEXTVERTADJUST_BLOCK: nVerAlign = EXC_OBJ_VER_JUSTIFY; break;
}
return nVerAlign;
}
XclTxo::XclTxo( const String& rString, sal_uInt16 nFontIx ) :
mpString( new XclExpString( rString ) ),
mnRotation( EXC_OBJ_ORIENT_NONE ),
mnHorAlign( EXC_OBJ_HOR_LEFT ),
mnVerAlign( EXC_OBJ_VER_TOP )
{
if( mpString->Len() )
{
// If there is text, Excel *needs* the 2nd CONTINUE record with at least two format runs
mpString->AppendFormat( 0, nFontIx );
mpString->AppendFormat( mpString->Len(), EXC_FONT_APP );
}
}
XclTxo::XclTxo( const XclExpRoot& rRoot, const SdrTextObj& rTextObj ) :
mpString( XclExpStringHelper::CreateString( rRoot, rTextObj ) ),
mnRotation( EXC_OBJ_ORIENT_NONE ),
mnHorAlign( EXC_OBJ_HOR_LEFT ),
mnVerAlign( EXC_OBJ_VER_TOP )
{
// additional alignment and orientation items
const SfxItemSet& rItemSet = rTextObj.GetMergedItemSet();
// horizontal alignment
SetHorAlign( lcl_GetHorAlignFromItemSet( rItemSet ) );
// vertical alignment
SetVerAlign( lcl_GetVerAlignFromItemSet( rItemSet ) );
// rotation
long nAngle = rTextObj.GetRotateAngle();
if( (4500 < nAngle) && (nAngle < 13500) )
mnRotation = EXC_OBJ_ORIENT_90CCW;
else if( (22500 < nAngle) && (nAngle < 31500) )
mnRotation = EXC_OBJ_ORIENT_90CW;
else
mnRotation = EXC_OBJ_ORIENT_NONE;
}
XclTxo::XclTxo( const XclExpRoot& rRoot, const EditTextObject& rEditObj, SdrObject* pCaption ) :
mpString( XclExpStringHelper::CreateString( rRoot, rEditObj ) ),
mnRotation( EXC_OBJ_ORIENT_NONE ),
mnHorAlign( EXC_OBJ_HOR_LEFT ),
mnVerAlign( EXC_OBJ_VER_TOP )
{
if(pCaption)
{
// Excel has one alignment per NoteObject while Calc supports
// one alignment per paragraph - use the first paragraph
// alignment (if set) as our overall alignment.
String aParaText( rEditObj.GetText( 0 ) );
if( aParaText.Len() )
{
SfxItemSet aSet( rEditObj.GetParaAttribs( 0));
const SfxPoolItem* pItem = NULL;
if( aSet.GetItemState( EE_PARA_JUST, sal_True, &pItem ) == SFX_ITEM_SET )
{
SvxAdjust eEEAlign = static_cast< const SvxAdjustItem& >( *pItem ).GetAdjust();
pCaption->SetMergedItem( SvxAdjustItem( eEEAlign, EE_PARA_JUST ) );
}
}
const SfxItemSet& rItemSet = pCaption->GetMergedItemSet();
// horizontal alignment
SetHorAlign( lcl_GetHorAlignFromItemSet( rItemSet ) );
// vertical alignment
SetVerAlign( lcl_GetVerAlignFromItemSet( rItemSet ) );
// orientation alignment
const SvxWritingModeItem& rItem = static_cast< const SvxWritingModeItem& >( rItemSet.Get( SDRATTR_TEXTDIRECTION ) );
if( rItem.GetValue() == com::sun::star::text::WritingMode_TB_RL )
mnRotation = EXC_OBJ_ORIENT_90CW;
}
}
void XclTxo::SaveCont( XclExpStream& rStrm )
{
DBG_ASSERT( mpString.get(), "XclTxo::SaveCont - missing string" );
// #i96858# do not save existing string formatting if text is empty
sal_uInt16 nRunLen = mpString->IsEmpty() ? 0 : (8 * mpString->GetFormatsCount());
// alignment
sal_uInt16 nFlags = 0;
::insert_value( nFlags, mnHorAlign, 1, 3 );
::insert_value( nFlags, mnVerAlign, 4, 3 );
rStrm << nFlags << mnRotation;
rStrm.WriteZeroBytes( 6 );
rStrm << mpString->Len() << nRunLen << sal_uInt32( 0 );
}
void XclTxo::Save( XclExpStream& rStrm )
{
// Write the TXO part
ExcRecord::Save( rStrm );
// CONTINUE records are only written if there is some text
if( !mpString->IsEmpty() )
{
// CONTINUE for character array
rStrm.StartRecord( EXC_ID_CONT, mpString->GetBufferSize() + 1 );
rStrm << static_cast< sal_uInt8 >( mpString->GetFlagField() & EXC_STRF_16BIT ); // only Unicode flag
mpString->WriteBuffer( rStrm );
rStrm.EndRecord();
// CONTINUE for formatting runs
rStrm.StartRecord( EXC_ID_CONT, 8 * mpString->GetFormatsCount() );
const XclFormatRunVec& rFormats = mpString->GetFormats();
for( XclFormatRunVec::const_iterator aIt = rFormats.begin(), aEnd = rFormats.end(); aIt != aEnd; ++aIt )
rStrm << aIt->mnChar << aIt->mnFontIdx << sal_uInt32( 0 );
rStrm.EndRecord();
}
}
sal_uInt16 XclTxo::GetNum() const
{
return EXC_ID_TXO;
}
sal_Size XclTxo::GetLen() const
{
return 18;
}
// --- class XclObjOle -------------------------------------------
XclObjOle::XclObjOle( XclExpObjectManager& rObjMgr, const SdrObject& rObj ) :
XclObj( rObjMgr, EXC_OBJTYPE_PICTURE ),
rOleObj( rObj ),
pRootStorage( rObjMgr.GetRoot().GetRootStorage() )
{
}
XclObjOle::~XclObjOle()
{
}
void XclObjOle::WriteSubRecs( XclExpStream& rStrm )
{
// write only as embedded, not linked
String aStorageName( RTL_CONSTASCII_USTRINGPARAM( "MBD" ) );
sal_Char aBuf[ sizeof(sal_uInt32) * 2 + 1 ];
// FIXME Eeek! Is this just a way to get a unique id?
sal_uInt32 nPictureId = sal_uInt32(sal_uIntPtr(this) >> 2);
sprintf( aBuf, "%08X", static_cast< unsigned int >( nPictureId ) ); // #100211# - checked
aStorageName.AppendAscii( aBuf );
SotStorageRef xOleStg = pRootStorage->OpenSotStorage( aStorageName,
STREAM_READWRITE| STREAM_SHARE_DENYALL );
if( xOleStg.Is() )
{
uno::Reference < embed::XEmbeddedObject > xObj( ((SdrOle2Obj&)rOleObj).GetObjRef() );
if ( xObj.is() )
{
// set version to "old" version, because it must be
// saved in MS notation.
sal_uInt32 nFl = 0;
SvtFilterOptions* pFltOpts = SvtFilterOptions::Get();
if( pFltOpts )
{
if( pFltOpts->IsMath2MathType() )
nFl |= OLE_STARMATH_2_MATHTYPE;
if( pFltOpts->IsWriter2WinWord() )
nFl |= OLE_STARWRITER_2_WINWORD;
if( pFltOpts->IsCalc2Excel() )
nFl |= OLE_STARCALC_2_EXCEL;
if( pFltOpts->IsImpress2PowerPoint() )
nFl |= OLE_STARIMPRESS_2_POWERPOINT;
}
SvxMSExportOLEObjects aOLEExpFilt( nFl );
aOLEExpFilt.ExportOLEObject( xObj, *xOleStg );
// OBJCF subrecord, undocumented as usual
rStrm.StartRecord( EXC_ID_OBJCF, 2 );
rStrm << sal_uInt16(0x0002);
rStrm.EndRecord();
// OBJFLAGS subrecord, undocumented as usual
rStrm.StartRecord( EXC_ID_OBJFLAGS, 2 );
sal_uInt16 nFlags = EXC_OBJ_PIC_MANUALSIZE;
::set_flag( nFlags, EXC_OBJ_PIC_SYMBOL, ((SdrOle2Obj&)rOleObj).GetAspect() == embed::Aspects::MSOLE_ICON );
rStrm << nFlags;
rStrm.EndRecord();
// OBJPICTFMLA subrecord, undocumented as usual
XclExpString aName( xOleStg->GetUserName() );
sal_uInt16 nPadLen = (sal_uInt16)(aName.GetSize() & 0x01);
sal_uInt16 nFmlaLen = static_cast< sal_uInt16 >( 12 + aName.GetSize() + nPadLen );
sal_uInt16 nSubRecLen = nFmlaLen + 6;
rStrm.StartRecord( EXC_ID_OBJPICTFMLA, nSubRecLen );
rStrm << nFmlaLen
<< sal_uInt16( 5 ) << sal_uInt32( 0 ) << sal_uInt8( 2 )
<< sal_uInt32( 0 ) << sal_uInt8( 3 )
<< aName;
if( nPadLen )
rStrm << sal_uInt8( 0 ); // pad byte
rStrm << nPictureId;
rStrm.EndRecord();
}
}
}
void XclObjOle::Save( XclExpStream& rStrm )
{
// content of this record
XclObj::Save( rStrm );
}
// --- class XclObjAny -------------------------------------------
XclObjAny::XclObjAny( XclExpObjectManager& rObjMgr ) :
XclObj( rObjMgr, EXC_OBJTYPE_UNKNOWN )
{
}
XclObjAny::~XclObjAny()
{
}
void XclObjAny::WriteSubRecs( XclExpStream& rStrm )
{
if( mnObjType == EXC_OBJTYPE_GROUP )
// ftGmo subrecord
rStrm << EXC_ID_OBJGMO << sal_uInt16(2) << sal_uInt16(0);
}
void XclObjAny::Save( XclExpStream& rStrm )
{
if( mnObjType == EXC_OBJTYPE_GROUP )
// old size + ftGmo
AddRecSize( 6 );
// content of this record
XclObj::Save( rStrm );
}
// --- class ExcBof8_Base --------------------------------------------
ExcBof8_Base::ExcBof8_Base()
{
nVers = 0x0600;
nRupBuild = 0x0dbb;
nRupYear = 0x07cc;
// nFileHistory = 0x00000001; // last edited by Microsoft Excel for Windows
nFileHistory = 0x00000000;
nLowestBiffVer = 0x00000006; // Biff8
}
void ExcBof8_Base::SaveCont( XclExpStream& rStrm )
{
rStrm.DisableEncryption();
rStrm << nVers << nDocType << nRupBuild << nRupYear
<< nFileHistory << nLowestBiffVer;
}
sal_uInt16 ExcBof8_Base::GetNum() const
{
return 0x0809;
}
sal_Size ExcBof8_Base::GetLen() const
{
return 16;
}
// --- class ExcBof8 -------------------------------------------------
ExcBof8::ExcBof8()
{
nDocType = 0x0010;
}
// --- class ExcBofW8 ------------------------------------------------
ExcBofW8::ExcBofW8()
{
nDocType = 0x0005;
}
// --- class ExcBundlesheet8 -----------------------------------------
ExcBundlesheet8::ExcBundlesheet8( RootData& rRootData, SCTAB _nTab ) :
ExcBundlesheetBase( rRootData, static_cast<sal_uInt16>(_nTab) ),
sUnicodeName( rRootData.pER->GetTabInfo().GetScTabName( _nTab ) )
{
}
ExcBundlesheet8::ExcBundlesheet8( const String& rString ) :
ExcBundlesheetBase(),
sUnicodeName( rString )
{
}
XclExpString ExcBundlesheet8::GetName() const
{
return XclExpString( sUnicodeName, EXC_STR_8BITLENGTH );
}
void ExcBundlesheet8::SaveCont( XclExpStream& rStrm )
{
nOwnPos = rStrm.GetSvStreamPos();
// write dummy position, real position comes later
rStrm.DisableEncryption();
rStrm << sal_uInt32(0);
rStrm.EnableEncryption();
rStrm << nGrbit << GetName();
}
sal_Size ExcBundlesheet8::GetLen() const
{ // Text max 255 chars
return 8 + GetName().GetBufferSize();
}
void ExcBundlesheet8::SaveXml( XclExpXmlStream& rStrm )
{
OUString sId;
rStrm.CreateOutputStream(
XclXmlUtils::GetStreamName( "xl/", "worksheets/sheet", nTab+1),
XclXmlUtils::GetStreamName( NULL, "worksheets/sheet", nTab+1),
rStrm.GetCurrentStream()->getOutputStream(),
"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",
&sId );
rStrm.GetCurrentStream()->singleElement( XML_sheet,
XML_name, XclXmlUtils::ToOString( sUnicodeName ).getStr(),
XML_sheetId, rtl::OString::valueOf( (sal_Int32)( nTab+1 ) ).getStr(),
XML_state, nGrbit == 0x0000 ? "visible" : "hidden",
FSNS( XML_r, XML_id ), XclXmlUtils::ToOString( sId ).getStr(),
FSEND );
}
// --- class XclObproj -----------------------------------------------
sal_uInt16 XclObproj::GetNum() const
{
return 0x00D3;
}
sal_Size XclObproj::GetLen() const
{
return 0;
}
// ---- class XclCodename --------------------------------------------
XclCodename::XclCodename( const String& r ) : aName( r )
{
}
void XclCodename::SaveCont( XclExpStream& rStrm )
{
rStrm << aName;
}
sal_uInt16 XclCodename::GetNum() const
{
return 0x01BA;
}
sal_Size XclCodename::GetLen() const
{
return aName.GetSize();
}
// ---- Scenarios ----------------------------------------------------
ExcEScenarioCell::ExcEScenarioCell( sal_uInt16 nC, sal_uInt16 nR, const String& rTxt ) :
nCol( nC ),
nRow( nR ),
sText( rTxt, EXC_STR_DEFAULT, 255 )
{
}
void ExcEScenarioCell::WriteAddress( XclExpStream& rStrm )
{
rStrm << nRow << nCol;
}
void ExcEScenarioCell::WriteText( XclExpStream& rStrm )
{
rStrm << sText;
}
void ExcEScenarioCell::SaveXml( XclExpXmlStream& rStrm )
{
rStrm.GetCurrentStream()->singleElement( XML_inputCells,
// OOXTODO: XML_deleted,
// OOXTODO: XML_numFmtId,
XML_r, XclXmlUtils::ToOString( ScAddress( nCol, nRow, 0 ) ).getStr(),
// OOXTODO: XML_undone,
XML_val, XclXmlUtils::ToOString( sText ).getStr(),
FSEND );
}
ExcEScenario::ExcEScenario( const XclExpRoot& rRoot, SCTAB nTab )
{
String sTmpName;
String sTmpComm;
Color aDummyCol;
sal_uInt16 nFlags;
ScDocument& rDoc = rRoot.GetDoc();
rDoc.GetName( nTab, sTmpName );
sName.Assign( sTmpName, EXC_STR_8BITLENGTH );
nRecLen = 8 + sName.GetBufferSize();
rDoc.GetScenarioData( nTab, sTmpComm, aDummyCol, nFlags );
sComment.Assign( sTmpComm, EXC_STR_DEFAULT, 255 );
if( sComment.Len() )
nRecLen += sComment.GetSize();
nProtected = (nFlags & SC_SCENARIO_PROTECT) ? 1 : 0;
sUserName.Assign( rRoot.GetUserName(), EXC_STR_DEFAULT, 255 );
nRecLen += sUserName.GetSize();
const ScRangeList* pRList = rDoc.GetScenarioRanges( nTab );
if( !pRList )
return;
sal_Bool bContLoop = sal_True;
SCROW nRow;
SCCOL nCol;
String sText;
double fVal;
for( sal_uInt32 nRange = 0; (nRange < pRList->Count()) && bContLoop; nRange++ )
{
const ScRange* pRange = pRList->GetObject( nRange );
for( nRow = pRange->aStart.Row(); (nRow <= pRange->aEnd.Row()) && bContLoop; nRow++ )
for( nCol = pRange->aStart.Col(); (nCol <= pRange->aEnd.Col()) && bContLoop; nCol++ )
{
if( rDoc.HasValueData( nCol, nRow, nTab ) )
{
rDoc.GetValue( nCol, nRow, nTab, fVal );
sText = ::rtl::math::doubleToUString( fVal,
rtl_math_StringFormat_Automatic,
rtl_math_DecimalPlaces_Max,
ScGlobal::pLocaleData->getNumDecimalSep().GetChar(0),
sal_True );
}
else
rDoc.GetString( nCol, nRow, nTab, sText );
bContLoop = Append( static_cast<sal_uInt16>(nCol),
static_cast<sal_uInt16>(nRow), sText );
}
}
}
ExcEScenario::~ExcEScenario()
{
for( ExcEScenarioCell* pCell = _First(); pCell; pCell = _Next() )
delete pCell;
}
sal_Bool ExcEScenario::Append( sal_uInt16 nCol, sal_uInt16 nRow, const String& rTxt )
{
if( List::Count() == EXC_SCEN_MAXCELL )
return sal_False;
ExcEScenarioCell* pCell = new ExcEScenarioCell( nCol, nRow, rTxt );
List::Insert( pCell, LIST_APPEND );
nRecLen += 6 + pCell->GetStringBytes(); // 4 bytes address, 2 bytes ifmt
return sal_True;
}
void ExcEScenario::SaveCont( XclExpStream& rStrm )
{
rStrm << (sal_uInt16) List::Count() // number of cells
<< nProtected // fProtection
<< (sal_uInt8) 0 // fHidden
<< (sal_uInt8) sName.Len() // length of scen name
<< (sal_uInt8) sComment.Len() // length of comment
<< (sal_uInt8) sUserName.Len(); // length of user name
sName.WriteFlagField( rStrm );
sName.WriteBuffer( rStrm );
rStrm << sUserName;
if( sComment.Len() )
rStrm << sComment;
ExcEScenarioCell* pCell;
for( pCell = _First(); pCell; pCell = _Next() )
pCell->WriteAddress( rStrm ); // pos of cell
for( pCell = _First(); pCell; pCell = _Next() )
pCell->WriteText( rStrm ); // string content
rStrm.SetSliceSize( 2 );
rStrm.WriteZeroBytes( 2 * List::Count() ); // date format
}
sal_uInt16 ExcEScenario::GetNum() const
{
return 0x00AF;
}
sal_Size ExcEScenario::GetLen() const
{
return nRecLen;
}
void ExcEScenario::SaveXml( XclExpXmlStream& rStrm )
{
sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
rWorkbook->startElement( XML_scenario,
XML_name, XclXmlUtils::ToOString( sName ).getStr(),
XML_locked, XclXmlUtils::ToPsz( nProtected ),
// OOXTODO: XML_hidden,
XML_count, OString::valueOf( (sal_Int32) List::Count() ).getStr(),
XML_user, XESTRING_TO_PSZ( sUserName ),
XML_comment, XESTRING_TO_PSZ( sComment ),
FSEND );
for( ExcEScenarioCell* pCell = _First(); pCell; pCell = _Next() )
pCell->SaveXml( rStrm );
rWorkbook->endElement( XML_scenario );
}
ExcEScenarioManager::ExcEScenarioManager( const XclExpRoot& rRoot, SCTAB nTab ) :
nActive( 0 )
{
ScDocument& rDoc = rRoot.GetDoc();
if( rDoc.IsScenario( nTab ) )
return;
SCTAB nFirstTab = nTab + 1;
SCTAB nNewTab = nFirstTab;
while( rDoc.IsScenario( nNewTab ) )
{
Append( new ExcEScenario( rRoot, nNewTab ) );
if( rDoc.IsActiveScenario( nNewTab ) )
nActive = static_cast<sal_uInt16>(nNewTab - nFirstTab);
nNewTab++;
}
}
ExcEScenarioManager::~ExcEScenarioManager()
{
for( ExcEScenario* pScen = _First(); pScen; pScen = _Next() )
delete pScen;
}
void ExcEScenarioManager::SaveCont( XclExpStream& rStrm )
{
rStrm << (sal_uInt16) List::Count() // number of scenarios
<< nActive // active scen
<< nActive // last displayed
<< (sal_uInt16) 0; // reference areas
}
void ExcEScenarioManager::Save( XclExpStream& rStrm )
{
if( List::Count() )
ExcRecord::Save( rStrm );
for( ExcEScenario* pScen = _First(); pScen; pScen = _Next() )
pScen->Save( rStrm );
}
void ExcEScenarioManager::SaveXml( XclExpXmlStream& rStrm )
{
if( ! List::Count() )
return;
sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
rWorkbook->startElement( XML_scenarios,
XML_current, OString::valueOf( (sal_Int32)nActive ).getStr(),
XML_show, OString::valueOf( (sal_Int32)nActive ).getStr(),
// OOXTODO: XML_sqref,
FSEND );
for( ExcEScenario* pScen = _First(); pScen; pScen = _Next() )
pScen->SaveXml( rStrm );
rWorkbook->endElement( XML_scenarios );
}
sal_uInt16 ExcEScenarioManager::GetNum() const
{
return 0x00AE;
}
sal_Size ExcEScenarioManager::GetLen() const
{
return 8;
}
// ============================================================================
struct XclExpTabProtectOption
{
ScTableProtection::Option eOption;
sal_uInt16 nMask;
};
XclExpSheetProtectOptions::XclExpSheetProtectOptions( const XclExpRoot& rRoot, SCTAB nTab ) :
XclExpRecord( 0x0867, 23 )
{
static const XclExpTabProtectOption aTable[] =
{
{ ScTableProtection::OBJECTS, 0x0001 },
{ ScTableProtection::SCENARIOS, 0x0002 },
{ ScTableProtection::FORMAT_CELLS, 0x0004 },
{ ScTableProtection::FORMAT_COLUMNS, 0x0008 },
{ ScTableProtection::FORMAT_ROWS, 0x0010 },
{ ScTableProtection::INSERT_COLUMNS, 0x0020 },
{ ScTableProtection::INSERT_ROWS, 0x0040 },
{ ScTableProtection::INSERT_HYPERLINKS, 0x0080 },
{ ScTableProtection::DELETE_COLUMNS, 0x0100 },
{ ScTableProtection::DELETE_ROWS, 0x0200 },
{ ScTableProtection::SELECT_LOCKED_CELLS, 0x0400 },
{ ScTableProtection::SORT, 0x0800 },
{ ScTableProtection::AUTOFILTER, 0x1000 },
{ ScTableProtection::PIVOT_TABLES, 0x2000 },
{ ScTableProtection::SELECT_UNLOCKED_CELLS, 0x4000 },
{ ScTableProtection::NONE, 0x0000 }
};
mnOptions = 0x0000;
ScTableProtection* pProtect = rRoot.GetDoc().GetTabProtection(nTab);
if (!pProtect)
return;
for (int i = 0; aTable[i].nMask != 0x0000; ++i)
{
if ( pProtect->isOptionEnabled(aTable[i].eOption) )
mnOptions |= aTable[i].nMask;
}
}
void XclExpSheetProtectOptions::WriteBody( XclExpStream& rStrm )
{
sal_uInt16 nBytes = 0x0867;
rStrm << nBytes;
sal_uChar nZero = 0x00;
for (int i = 0; i < 9; ++i)
rStrm << nZero;
nBytes = 0x0200;
rStrm << nBytes;
nBytes = 0x0100;
rStrm << nBytes;
nBytes = 0xFFFF;
rStrm << nBytes << nBytes;
rStrm << mnOptions;
nBytes = 0;
rStrm << nBytes;
}
// ============================================================================
void XclCalccount::SaveCont( XclExpStream& rStrm )
{
rStrm << nCount;
}
XclCalccount::XclCalccount( const ScDocument& rDoc )
{
nCount = rDoc.GetDocOptions().GetIterCount();
}
sal_uInt16 XclCalccount::GetNum() const
{
return 0x000C;
}
sal_Size XclCalccount::GetLen() const
{
return 2;
}
void XclCalccount::SaveXml( XclExpXmlStream& rStrm )
{
rStrm.WriteAttributes(
XML_iterateCount, OString::valueOf( (sal_Int32)nCount ).getStr(),
FSEND );
}
void XclIteration::SaveCont( XclExpStream& rStrm )
{
rStrm << nIter;
}
XclIteration::XclIteration( const ScDocument& rDoc )
{
nIter = rDoc.GetDocOptions().IsIter()? 1 : 0;
}
sal_uInt16 XclIteration::GetNum() const
{
return 0x0011;
}
sal_Size XclIteration::GetLen() const
{
return 2;
}
void XclIteration::SaveXml( XclExpXmlStream& rStrm )
{
rStrm.WriteAttributes(
XML_iterate, XclXmlUtils::ToPsz( nIter == 1 ),
FSEND );
}
void XclDelta::SaveCont( XclExpStream& rStrm )
{
rStrm << fDelta;
}
XclDelta::XclDelta( const ScDocument& rDoc )
{
fDelta = rDoc.GetDocOptions().GetIterEps();
}
sal_uInt16 XclDelta::GetNum() const
{
return 0x0010;
}
sal_Size XclDelta::GetLen() const
{
return 8;
}
void XclDelta::SaveXml( XclExpXmlStream& rStrm )
{
rStrm.WriteAttributes(
XML_iterateDelta, OString::valueOf( fDelta ).getStr(),
FSEND );
}
// ============================================================================
XclExpFileEncryption::XclExpFileEncryption( const XclExpRoot& rRoot ) :
XclExpRecord(0x002F, 54),
mrRoot(rRoot)
{
}
XclExpFileEncryption::~XclExpFileEncryption()
{
}
void XclExpFileEncryption::WriteBody( XclExpStream& rStrm )
{
// 0x0000 - neither standard nor strong encryption
// 0x0001 - standard or strong encryption
rStrm << static_cast<sal_uInt16>(0x0001);
// 0x0000 - non standard encryption
// 0x0001 - standard encryption
sal_uInt16 nStdEnc = 0x0001;
rStrm << nStdEnc << nStdEnc;
sal_uInt8 pnDocId[16];
sal_uInt8 pnSalt[16];
sal_uInt8 pnSaltHash[16];
XclExpEncrypterRef xEnc( new XclExpBiff8Encrypter(mrRoot) );
xEnc->GetDocId(pnDocId);
xEnc->GetSalt(pnSalt);
xEnc->GetSaltDigest(pnSaltHash);
rStrm.Write(pnDocId, 16);
rStrm.Write(pnSalt, 16);
rStrm.Write(pnSaltHash, 16);
rStrm.SetEncrypter(xEnc);
}
// ============================================================================
XclExpInterfaceHdr::XclExpInterfaceHdr( sal_uInt16 nCodePage ) :
XclExpUInt16Record( EXC_ID_INTERFACEHDR, nCodePage )
{
}
void XclExpInterfaceHdr::WriteBody( XclExpStream& rStrm )
{
rStrm.DisableEncryption();
rStrm << GetValue();
}
// ============================================================================
XclExpInterfaceEnd::XclExpInterfaceEnd() :
XclExpRecord(0x00E2, 0) {}
XclExpInterfaceEnd::~XclExpInterfaceEnd() {}
void XclExpInterfaceEnd::WriteBody( XclExpStream& rStrm )
{
// Don't forget to re-enable encryption.
rStrm.EnableEncryption();
}
// ============================================================================
XclExpWriteAccess::XclExpWriteAccess() :
XclExpRecord(0x005C, 112)
{
}
XclExpWriteAccess::~XclExpWriteAccess()
{
}
void XclExpWriteAccess::WriteBody( XclExpStream& rStrm )
{
static const sal_uInt8 aData[] = {
0x04, 0x00, 0x00, 'C', 'a', 'l', 'c', 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
sal_Size nDataSize = sizeof(aData);
for (sal_Size i = 0; i < nDataSize; ++i)
rStrm << aData[i];
}
// ============================================================================
XclExpFileSharing::XclExpFileSharing( const XclExpRoot& rRoot, sal_uInt16 nPasswordHash, bool bRecommendReadOnly ) :
XclExpRecord( EXC_ID_FILESHARING ),
mnPasswordHash( nPasswordHash ),
mbRecommendReadOnly( bRecommendReadOnly )
{
if( rRoot.GetBiff() <= EXC_BIFF5 )
maUserName.AssignByte( rRoot.GetUserName(), rRoot.GetTextEncoding(), EXC_STR_8BITLENGTH );
else
maUserName.Assign( rRoot.GetUserName() );
}
void XclExpFileSharing::Save( XclExpStream& rStrm )
{
if( (mnPasswordHash != 0) || mbRecommendReadOnly )
XclExpRecord::Save( rStrm );
}
void XclExpFileSharing::WriteBody( XclExpStream& rStrm )
{
rStrm << sal_uInt16( mbRecommendReadOnly ? 1 : 0 ) << mnPasswordHash << maUserName;
}
// ============================================================================
XclExpProt4Rev::XclExpProt4Rev() :
XclExpRecord(0x01AF, 2)
{
}
XclExpProt4Rev::~XclExpProt4Rev()
{
}
void XclExpProt4Rev::WriteBody( XclExpStream& rStrm )
{
rStrm << static_cast<sal_uInt16>(0x0000);
}
// ============================================================================
XclExpProt4RevPass::XclExpProt4RevPass() :
XclExpRecord(0x01BC, 2)
{
}
XclExpProt4RevPass::~XclExpProt4RevPass()
{
}
void XclExpProt4RevPass::WriteBody( XclExpStream& rStrm )
{
rStrm << static_cast<sal_uInt16>(0x0000);
}
// ============================================================================
static const sal_uInt8 nDataRecalcId[] = {
0xC1, 0x01, 0x00, 0x00, 0x54, 0x8D, 0x01, 0x00
};
XclExpRecalcId::XclExpRecalcId() :
XclExpDummyRecord(0x01C1, nDataRecalcId, sizeof(nDataRecalcId))
{
}
// ============================================================================
static const sal_uInt8 nDataBookExt[] = {
0x63, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02
};
XclExpBookExt::XclExpBookExt() :
XclExpDummyRecord(0x0863, nDataBookExt, sizeof(nDataBookExt))
{
}
// ============================================================================
XclRefmode::XclRefmode( const ScDocument& rDoc ) :
XclExpBoolRecord( 0x000F, rDoc.GetAddressConvention() != formula::FormulaGrammar::CONV_XL_R1C1 )
{
}
void XclRefmode::SaveXml( XclExpXmlStream& rStrm )
{
rStrm.WriteAttributes(
XML_refMode, GetBool() ? "A1" : "R1C1",
FSEND );
}