1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svx/sdtaitm.hxx>
21 #include <svx/svdotext.hxx>
22 #include <editeng/editobj.hxx>
23 #include <svx/svdoole2.hxx>
24 #include <sot/storage.hxx>
25 #include <svl/itemset.hxx>
26 #include <svx/svdocapt.hxx>
27 #include <svx/unoapi.hxx>
28 #include <editeng/writingmodeitem.hxx>
29 #include <tools/urlobj.hxx>
31 #include <rtl/math.hxx>
33 #include <sal/log.hxx>
34 #include <drwlayer.hxx>
37 #include <xcl97rec.hxx>
38 #include <xcl97esc.hxx>
39 #include <xeescher.hxx>
40 #include <xehelper.hxx>
42 #include <xlcontent.hxx>
44 #include <unotools/fltrcfg.hxx>
45 #include <editeng/adjustitem.hxx>
46 #include <editeng/eeitem.hxx>
47 #include <filter/msfilter/msoleexp.hxx>
49 #include <unotools/localedatawrapper.hxx>
53 #include <document.hxx>
54 #include <rangelst.hxx>
55 #include <docoptio.hxx>
56 #include <tabprotection.hxx>
58 #include <com/sun/star/embed/Aspects.hpp>
59 #include <com/sun/star/chart/XChartDocument.hpp>
60 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
61 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
62 #include <com/sun/star/chart2/XChartDocument.hpp>
64 #include <sax/fastattribs.hxx>
65 #include <oox/token/tokens.hxx>
66 #include <oox/token/namespaces.hxx>
67 #include <oox/token/relationship.hxx>
68 #include <oox/export/shapes.hxx>
69 #include <oox/export/utils.hxx>
70 #include <oox/export/vmlexport.hxx>
71 #include <detfunc.hxx>
75 using namespace ::com::sun::star
;
76 using ::com::sun::star::uno::Reference
;
77 using ::com::sun::star::uno::UNO_QUERY
;
78 using ::com::sun::star::beans::XPropertySet
;
79 using ::com::sun::star::drawing::XShape
;
80 using ::oox::drawingml::ShapeExport
;
81 using ::oox::vml::VMLExport
;
84 XclExpObjList::XclExpObjList( const XclExpRoot
& rRoot
, XclEscherEx
& rEscherEx
) :
86 mnScTab( rRoot
.GetCurrScTab() ),
87 mrEscherEx( rEscherEx
)
89 pMsodrawingPerSheet
.reset( new XclExpMsoDrawing( rEscherEx
) );
90 // open the DGCONTAINER and the patriarch group shape
91 mrEscherEx
.OpenContainer( ESCHER_DgContainer
);
92 tools::Rectangle
aRect( 0, 0, 0, 0 );
93 mrEscherEx
.EnterGroup( &aRect
);
94 mrEscherEx
.UpdateDffFragmentEnd();
97 XclExpObjList::~XclExpObjList()
100 pMsodrawingPerSheet
.reset();
101 pSolverContainer
.reset();
104 sal_uInt16
XclExpObjList::Add( std::unique_ptr
<XclObj
> pObj
)
106 OSL_ENSURE( maObjs
.size() < 0xFFFF, "XclExpObjList::Add: too much for Xcl" );
108 size_t nSize
= maObjs
.size();
110 if ( nSize
< 0xFFFF )
112 pObj
->SetId( nSize
+1 );
113 pObj
->SetTab( mnScTab
);
114 maObjs
.push_back(std::move(pObj
));
125 std::unique_ptr
<XclObj
> XclExpObjList::pop_back ()
127 auto ret
= std::move(maObjs
.back());
132 void XclExpObjList::EndSheet()
134 // Is there still something in the stream? -> The solver container
135 if( mrEscherEx
.HasPendingDffData() )
136 pSolverContainer
.reset( new XclExpMsoDrawing( mrEscherEx
) );
138 // close the DGCONTAINER created by XclExpObjList ctor MSODRAWING
139 mrEscherEx
.CloseContainer();
142 void XclExpObjList::Save( XclExpStream
& rStrm
)
144 //! Escher must be written, even if there are no objects
145 pMsodrawingPerSheet
->Save( rStrm
);
147 for ( const auto& rxObj
: maObjs
)
148 rxObj
->Save( rStrm
);
150 if( pSolverContainer
)
151 pSolverContainer
->Save( rStrm
);
156 bool IsFormControlObject( const XclObj
*rObj
)
158 switch( rObj
->GetObjType() )
160 case EXC_OBJTYPE_CHECKBOX
:
161 case EXC_OBJTYPE_BUTTON
:
168 bool IsVmlObject( const XclObj
*rObj
)
170 switch( rObj
->GetObjType() )
172 case EXC_OBJTYPE_NOTE
:
179 sal_Int32
GetVmlObjectCount( XclExpObjList
& rList
)
181 return static_cast<sal_Int32
>(std::count_if(rList
.begin(), rList
.end(),
182 [](const std::unique_ptr
<XclObj
>& rxObj
) { return IsVmlObject( rxObj
.get() ) || IsFormControlObject( rxObj
.get() ); }));
185 bool IsValidObject( const XclObj
& rObj
)
187 if (rObj
.GetObjType() == EXC_OBJTYPE_CHART
)
189 // Chart object. Make sure it's a valid chart object. We skip
190 // invalid chart objects from exporting to prevent Excel from
191 // complaining on load.
193 const XclExpChartObj
& rChartObj
= static_cast<const XclExpChartObj
&>(rObj
);
194 uno::Reference
<chart2::XChartDocument
> xChartDoc(rChartObj
.GetChartDoc(), uno::UNO_QUERY
);
198 uno::Reference
<chart2::XDiagram
> xDiagram
= xChartDoc
->getFirstDiagram();
202 uno::Reference
<chart2::XCoordinateSystemContainer
> xCooSysContainer(xDiagram
, uno::UNO_QUERY
);
203 if (!xCooSysContainer
.is())
206 const uno::Sequence
<uno::Reference
<chart2::XCoordinateSystem
>> xCooSysSeq
= xCooSysContainer
->getCoordinateSystems();
207 for (const auto& rCooSys
: xCooSysSeq
)
209 Reference
<chart2::XChartTypeContainer
> xChartTypeCont(rCooSys
, uno::UNO_QUERY
);
210 if (!xChartTypeCont
.is())
213 uno::Sequence
<uno::Reference
<chart2::XChartType
>> xChartTypeSeq
= xChartTypeCont
->getChartTypes();
214 if (!xChartTypeSeq
.hasElements())
215 // No chart type. Not good.
223 void SaveDrawingMLObjects( XclExpObjList
& rList
, XclExpXmlStream
& rStrm
)
225 std::vector
<XclObj
*> aList
;
226 aList
.reserve(rList
.size());
227 for (const auto& rxObj
: rList
)
229 if (IsVmlObject(rxObj
.get()) || !IsValidObject(*rxObj
))
232 aList
.push_back(rxObj
.get());
238 sal_Int32 nDrawing
= drawingml::DrawingML::getNewDrawingUniqueId();
240 sax_fastparser::FSHelperPtr pDrawing
= rStrm
.CreateOutputStream(
241 XclXmlUtils::GetStreamName( "xl/", "drawings/drawing", nDrawing
),
242 XclXmlUtils::GetStreamName( "../", "drawings/drawing", nDrawing
),
243 rStrm
.GetCurrentStream()->getOutputStream(),
244 "application/vnd.openxmlformats-officedocument.drawing+xml",
245 oox::getRelationship(Relationship::DRAWING
),
248 rStrm
.GetCurrentStream()->singleElement(XML_drawing
, FSNS(XML_r
, XML_id
), sId
.toUtf8());
250 rStrm
.PushStream( pDrawing
);
251 pDrawing
->startElement( FSNS( XML_xdr
, XML_wsDr
),
252 FSNS(XML_xmlns
, XML_xdr
), rStrm
.getNamespaceURL(OOX_NS(dmlSpreadDr
)).toUtf8(),
253 FSNS(XML_xmlns
, XML_a
), rStrm
.getNamespaceURL(OOX_NS(dml
)).toUtf8(),
254 FSNS(XML_xmlns
, XML_r
), rStrm
.getNamespaceURL(OOX_NS(officeRel
)).toUtf8() );
256 sal_Int32 nShapeId
= 1000; // unique id of the shape inside one worksheet (not the whole document)
257 for (const auto& rpObj
: aList
)
260 if ( IsFormControlObject( rpObj
) )
262 XclExpTbxControlObj
* pXclExpTbxControlObj
= dynamic_cast<XclExpTbxControlObj
*>(rpObj
);
263 if (pXclExpTbxControlObj
)
265 pXclExpTbxControlObj
->setShapeId(++nShapeId
);
269 rpObj
->SaveXml(rStrm
);
272 pDrawing
->endElement( FSNS( XML_xdr
, XML_wsDr
) );
277 void SaveFormControlObjects(XclExpObjList
& rList
, XclExpXmlStream
& rStrm
)
279 bool hasControls
= false;
280 for (const auto& rxObj
: rList
)
282 if (IsFormControlObject(rxObj
.get()))
294 sax_fastparser::FSHelperPtr
& rWorksheet
= rStrm
.GetCurrentStream();
296 rWorksheet
->startElement(FSNS(XML_mc
, XML_AlternateContent
),
297 FSNS(XML_xmlns
, XML_mc
), rStrm
.getNamespaceURL(OOX_NS(mce
)).toUtf8());
298 rWorksheet
->startElement(FSNS(XML_mc
, XML_Choice
), XML_Requires
, "x14");
299 rWorksheet
->startElement(XML_controls
);
301 for (const auto& rxObj
: rList
)
303 if (IsFormControlObject(rxObj
.get()))
305 XclExpTbxControlObj
* pXclExpTbxControlObj
= dynamic_cast<XclExpTbxControlObj
*>(rxObj
.get());
306 if (pXclExpTbxControlObj
)
308 const OUString aIdFormControlPr
= pXclExpTbxControlObj
->SaveControlPropertiesXml(rStrm
);
309 pXclExpTbxControlObj
->SaveSheetXml(rStrm
, aIdFormControlPr
);
314 rWorksheet
->endElement(XML_controls
);
315 rWorksheet
->endElement(FSNS(XML_mc
, XML_Choice
));
316 rWorksheet
->endElement(FSNS(XML_mc
, XML_AlternateContent
));
319 void SaveVmlObjects( XclExpObjList
& rList
, XclExpXmlStream
& rStrm
)
321 if( GetVmlObjectCount( rList
) == 0 )
324 sal_Int32 nDrawing
= drawingml::DrawingML::getNewVMLUniqueId();
326 sax_fastparser::FSHelperPtr pVmlDrawing
= rStrm
.CreateOutputStream(
327 XclXmlUtils::GetStreamName( "xl/", "drawings/vmlDrawing", nDrawing
),
328 XclXmlUtils::GetStreamName( "../", "drawings/vmlDrawing", nDrawing
),
329 rStrm
.GetCurrentStream()->getOutputStream(),
330 "application/vnd.openxmlformats-officedocument.vmlDrawing",
331 oox::getRelationship(Relationship::VMLDRAWING
),
334 rStrm
.GetCurrentStream()->singleElement(XML_legacyDrawing
, FSNS(XML_r
, XML_id
), sId
.toUtf8());
336 rStrm
.PushStream( pVmlDrawing
);
337 pVmlDrawing
->write("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
338 pVmlDrawing
->startElement( XML_xml
,
339 FSNS(XML_xmlns
, XML_v
), rStrm
.getNamespaceURL(OOX_NS(vml
)).toUtf8(),
340 FSNS(XML_xmlns
, XML_o
), rStrm
.getNamespaceURL(OOX_NS(vmlOffice
)).toUtf8(),
341 FSNS(XML_xmlns
, XML_x
), rStrm
.getNamespaceURL(OOX_NS(vmlExcel
)).toUtf8(),
342 FSNS(XML_xmlns
, XML_w10
), rStrm
.getNamespaceURL(OOX_NS(vmlWord
)).toUtf8() );
344 for ( const auto& rxObj
: rList
)
346 if (IsFormControlObject(rxObj
.get()))
348 auto pFormControlObject
= dynamic_cast<XclExpTbxControlObj
*>(rxObj
.get());
349 if (pFormControlObject
)
351 pFormControlObject
->SaveVml(rStrm
);
355 if( !IsVmlObject( rxObj
.get() ) )
357 rxObj
->SaveXml( rStrm
);
360 pVmlDrawing
->endElement( XML_xml
);
367 void XclExpObjList::SaveXml( XclExpXmlStream
& rStrm
)
369 if( pSolverContainer
)
370 pSolverContainer
->SaveXml( rStrm
);
375 SaveDrawingMLObjects( *this, rStrm
);
376 SaveVmlObjects( *this, rStrm
);
377 SaveFormControlObjects( *this, rStrm
);
380 // --- class XclObj --------------------------------------------------
382 XclObj::XclObj( XclExpObjectManager
& rObjMgr
, sal_uInt16 nObjType
, bool bOwnEscher
) :
383 XclExpRecord( EXC_ID_OBJ
, 26 ),
384 mrEscherEx( rObjMgr
.GetEscherEx() ),
385 mnObjType( nObjType
),
387 nGrbit( 0x6011 ), // AutoLine, AutoFill, Printable, Locked
389 bFirstOnSheet( !rObjMgr
.HasObj() ),
390 mbOwnEscher( bOwnEscher
)
392 //! first object continues the first MSODRAWING record
394 pMsodrawing
= rObjMgr
.GetMsodrawingPerSheet();
396 pMsodrawing
= new XclExpMsoDrawing( mrEscherEx
);
401 if ( !bFirstOnSheet
)
403 pClientTextbox
.reset();
407 void XclObj::ImplWriteAnchor( const SdrObject
* pSdrObj
, const tools::Rectangle
* pChildAnchor
)
411 mrEscherEx
.AddChildAnchor( *pChildAnchor
);
415 std::unique_ptr
< XclExpDffAnchorBase
> xDffAnchor( mrEscherEx
.CreateDffAnchor( *pSdrObj
) );
416 xDffAnchor
->WriteDffData( mrEscherEx
);
420 void XclObj::SetEscherShapeType( sal_uInt16 nType
)
422 //ToDo: what about the other defined or... types?
425 case ESCHER_ShpInst_Line
:
426 mnObjType
= EXC_OBJTYPE_LINE
;
428 case ESCHER_ShpInst_Rectangle
:
429 case ESCHER_ShpInst_RoundRectangle
:
430 mnObjType
= EXC_OBJTYPE_RECTANGLE
;
432 case ESCHER_ShpInst_Ellipse
:
433 mnObjType
= EXC_OBJTYPE_OVAL
;
435 case ESCHER_ShpInst_Arc
:
436 mnObjType
= EXC_OBJTYPE_ARC
;
438 case ESCHER_ShpInst_TextBox
:
439 mnObjType
= EXC_OBJTYPE_TEXT
;
441 case ESCHER_ShpInst_PictureFrame
:
442 mnObjType
= EXC_OBJTYPE_PICTURE
;
445 mnObjType
= EXC_OBJTYPE_DRAWING
;
449 void XclObj::SetText( const XclExpRoot
& rRoot
, const SdrTextObj
& rObj
)
451 OSL_ENSURE( !pClientTextbox
, "XclObj::SetText: already set" );
452 if ( !pClientTextbox
)
454 mrEscherEx
.UpdateDffFragmentEnd();
455 pClientTextbox
.reset( new XclExpMsoDrawing( mrEscherEx
) );
456 mrEscherEx
.AddAtom( 0, ESCHER_ClientTextbox
); // TXO record
457 mrEscherEx
.UpdateDffFragmentEnd();
458 pTxo
.reset( new XclTxo( rRoot
, rObj
) );
462 void XclObj::WriteBody( XclExpStream
& rStrm
)
464 OSL_ENSURE( mnObjType
!= EXC_OBJTYPE_UNKNOWN
, "XclObj::WriteBody - unknown type" );
466 // create a substream to be able to create subrecords
467 SvMemoryStream aMemStrm
;
468 std::optional
< XclExpStream
> pXclStrm( std::in_place
, aMemStrm
, rStrm
.GetRoot() );
470 // write the ftCmo subrecord
471 pXclStrm
->StartRecord( EXC_ID_OBJCMO
, 18 );
472 *pXclStrm
<< mnObjType
<< nObjId
<< nGrbit
;
473 pXclStrm
->WriteZeroBytes( 12 );
474 pXclStrm
->EndRecord();
476 // write other subrecords
477 WriteSubRecs( *pXclStrm
);
479 // write the ftEnd subrecord
480 pXclStrm
->StartRecord( EXC_ID_OBJEND
, 0 );
481 pXclStrm
->EndRecord();
483 // copy the data to the OBJ record
486 rStrm
.CopyFromStream( aMemStrm
);
489 void XclObj::Save( XclExpStream
& rStrm
)
491 // MSODRAWING record (msofbtSpContainer)
492 if ( !bFirstOnSheet
)
493 pMsodrawing
->Save( rStrm
);
496 XclExpRecord::Save( rStrm
);
498 // second MSODRAWING record and TXO and CONTINUE records
499 SaveTextRecs( rStrm
);
502 void XclObj::WriteSubRecs( XclExpStream
& rStrm
)
504 if( mnObjType
!= EXC_OBJTYPE_NOTE
)
510 rStrm
<< EXC_ID_OBJNTS
<< sal_uInt16(0x0016);
512 rtl_createUuid( aGUID
, nullptr, false );
514 rStrm
.SetSliceSize( 16 );
515 for( int i
= 0; i
< 16; i
++ )
517 rStrm
.SetSliceSize( 0 );
519 rStrm
<< sal_uInt16(0);
521 rStrm
.WriteZeroBytes( 4 );
524 void XclObj::SaveTextRecs( XclExpStream
& rStrm
)
526 // MSODRAWING record (msofbtClientTextbox)
527 if ( pClientTextbox
)
528 pClientTextbox
->Save( rStrm
);
529 // TXO and CONTINUE records
534 // --- class XclObjComment ------------------------------------------
536 // tdf#118662 static helper to allow single function access as friend in SdrCaptionObj
537 void setSuppressGetBitmapFromXclObjComment(SdrCaptionObj
* pSdrCaptionObj
, bool bValue
)
539 if(nullptr != pSdrCaptionObj
)
541 pSdrCaptionObj
->setSuppressGetBitmap(bValue
);
545 XclObjComment::XclObjComment( XclExpObjectManager
& rObjMgr
, const tools::Rectangle
& rRect
, const EditTextObject
& rEditObj
, SdrCaptionObj
* pCaption
, bool bVisible
, const ScAddress
& rAddress
, const tools::Rectangle
&rFrom
, const tools::Rectangle
&rTo
) :
546 XclObj( rObjMgr
, EXC_OBJTYPE_NOTE
, true )
547 , maScPos( rAddress
)
548 , mpCaption( pCaption
)
549 , mbVisible( bVisible
)
553 // tdf#118662 due to no longer cloning the SdrCaptionObj an old 'hack' using the
554 // fact that no Graphics gets created when a SdrObject is not inserted in a SdrPage
555 // does not work anymore. In SvxShape::GetBitmap that info was used, and here the
556 // SdrCaptionObj was cloned for the only reason to have one not added to a SdrPage.
557 // To emulate old behaviour, use a boolean flag at the SdrCaptionObj.
558 setSuppressGetBitmapFromXclObjComment(mpCaption
, true);
560 ProcessEscherObj( rObjMgr
.GetRoot(), rRect
, pCaption
, bVisible
);
562 pTxo
.reset(new XclTxo( rObjMgr
.GetRoot(), rEditObj
, pCaption
));
565 static void lcl_FillProps( EscherPropertyContainer
& rPropOpt
, SdrObject
* pCaption
, bool bVisible
)
569 Reference
< XShape
> aXShape
= GetXShapeForSdrObject( pCaption
);
570 Reference
< XPropertySet
> aXPropSet( aXShape
, UNO_QUERY
);
573 rPropOpt
.CreateFillProperties( aXPropSet
, true);
575 rPropOpt
.AddOpt( ESCHER_Prop_lTxid
, 0 ); // undocumented
576 rPropOpt
.AddOpt( 0x0158, 0x00000000 ); // undocumented
578 sal_uInt32 nValue
= 0;
579 if( !rPropOpt
.GetOpt( ESCHER_Prop_FitTextToShape
, nValue
) )
580 rPropOpt
.AddOpt( ESCHER_Prop_FitTextToShape
, 0x00080008 ); // bool field
582 // Maybe the colour is the same as the 'ToolTip' System colour, but the tooltip
583 // colour shouldn't have influence on the fill colour of the exported shape
584 if( !rPropOpt
.GetOpt( ESCHER_Prop_fillColor
, nValue
) )
585 rPropOpt
.AddOpt( ESCHER_Prop_fillColor
, 0x08000050 );
586 if( !rPropOpt
.GetOpt( ESCHER_Prop_fillBackColor
, nValue
) )
587 rPropOpt
.AddOpt( ESCHER_Prop_fillBackColor
, 0x08000050 );
588 if( !rPropOpt
.GetOpt( ESCHER_Prop_fNoFillHitTest
, nValue
) )
589 rPropOpt
.AddOpt( ESCHER_Prop_fNoFillHitTest
, 0x00110010 ); // bool field
590 if( !rPropOpt
.GetOpt( ESCHER_Prop_shadowColor
, nValue
) )
591 rPropOpt
.AddOpt( ESCHER_Prop_shadowColor
, 0x00000000 );
592 if( !rPropOpt
.GetOpt( ESCHER_Prop_fshadowObscured
, nValue
) ) // bool field
593 rPropOpt
.AddOpt( ESCHER_Prop_fshadowObscured
, 0x00030003 ); // bool field
597 sal_uInt32 nFlags
= 0x000A0000;
598 ::set_flag( nFlags
, sal_uInt32(2), !bVisible
);
599 rPropOpt
.AddOpt( ESCHER_Prop_fPrint
, nFlags
); // bool field
602 void XclObjComment::ProcessEscherObj( const XclExpRoot
& rRoot
, const tools::Rectangle
& rRect
, SdrObject
* pCaption
, const bool bVisible
)
604 EscherPropertyContainer aPropOpt
;
606 lcl_FillProps( aPropOpt
, pCaption
, bVisible
);
608 nGrbit
= 0; // all off: AutoLine, AutoFill, Printable, Locked
609 mrEscherEx
.OpenContainer( ESCHER_SpContainer
);
610 mrEscherEx
.AddShape( ESCHER_ShpInst_TextBox
, ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
);
611 aPropOpt
.Commit( mrEscherEx
.GetStream() );
613 XclExpDffNoteAnchor( rRoot
, rRect
).WriteDffData( mrEscherEx
);
615 mrEscherEx
.AddAtom( 0, ESCHER_ClientData
); // OBJ record
616 mrEscherEx
.UpdateDffFragmentEnd();
618 //! Be sure to construct the MSODRAWING ClientTextbox record _after_ the
619 //! base OBJ's MSODRAWING record Escher data is completed.
620 pClientTextbox
.reset( new XclExpMsoDrawing( mrEscherEx
) );
621 mrEscherEx
.AddAtom( 0, ESCHER_ClientTextbox
); // TXO record
622 mrEscherEx
.UpdateDffFragmentEnd();
623 mrEscherEx
.CloseContainer(); // ESCHER_SpContainer
626 XclObjComment::~XclObjComment()
628 // tdf#118662 reset flag
629 setSuppressGetBitmapFromXclObjComment(mpCaption
, false);
632 void XclObjComment::Save( XclExpStream
& rStrm
)
634 // content of this record
635 XclObj::Save( rStrm
);
640 class VmlCommentExporter
: public VMLExport
643 SdrCaptionObj
* mpCaption
;
645 tools::Rectangle maFrom
;
646 tools::Rectangle maTo
;
649 VmlCommentExporter ( const sax_fastparser::FSHelperPtr
& p
, const ScAddress
& aScPos
, SdrCaptionObj
* pCaption
, bool bVisible
, const tools::Rectangle
&aFrom
, const tools::Rectangle
&aTo
);
651 virtual void Commit( EscherPropertyContainer
& rProps
, const tools::Rectangle
& rRect
) override
;
652 using VMLExport::StartShape
;
653 virtual sal_Int32
StartShape() override
;
654 using VMLExport::EndShape
;
655 virtual void EndShape( sal_Int32 nShapeElement
) override
;
660 VmlCommentExporter::VmlCommentExporter( const sax_fastparser::FSHelperPtr
& p
, const ScAddress
& aScPos
, SdrCaptionObj
* pCaption
,
661 bool bVisible
, const tools::Rectangle
&aFrom
, const tools::Rectangle
&aTo
)
664 , mpCaption( pCaption
)
665 , mbVisible( bVisible
)
671 void VmlCommentExporter::Commit( EscherPropertyContainer
& rProps
, const tools::Rectangle
& rRect
)
673 lcl_FillProps( rProps
, mpCaption
, mbVisible
);
674 rProps
.AddOpt( ESCHER_Prop_fHidden
, sal_uInt32(mbVisible
) ); // bool field
676 // shadow property value for comment ( set in lcl_FillProps [*] ) has been
677 // overwritten by new value ( 0x20000 ) in the generic part of the export
678 // ( see EscherPropertyContainer::CreateShadowProperties )
679 // Safer option here is to just force the needed value here for oox vml
680 // export alone ( and avoid potential problems with binary export )
681 // #TODO investigate value of ESCHER_Prop_fshadowObscured generally
682 // in binary export ( if indeed this value is good for binary export )
683 // we can change the heuristics and/or initialisation path and get
684 // rid of line below.
685 // [*] lcl_FillProps seems to be called twice when exporting to xlsx
686 // once from XclObjComment::ProcessEscherObj #TODO look into that also
687 rProps
.AddOpt( ESCHER_Prop_fshadowObscured
, 0x00030003 ); // force value for comments
689 VMLExport::Commit( rProps
, rRect
);
692 sal_Int32
VmlCommentExporter::StartShape()
694 AddShapeAttribute( XML_type
, "#_x0000_t202" );
696 sal_Int32 nId
= VMLExport::StartShape();
701 static const char* lcl_GetHorizAlignFromItemSetChar(const SfxItemSet
& rItemSet
)
703 switch (rItemSet
.Get(EE_PARA_JUST
).GetAdjust())
705 case SvxAdjust::Center
:
707 case SvxAdjust::Right
:
709 case SvxAdjust::Block
:
716 static const char* lcl_GetVertAlignFromItemSetChar( const SfxItemSet
& rItemSet
)
718 switch( rItemSet
.Get( SDRATTR_TEXT_VERTADJUST
).GetValue() )
720 case SDRTEXTVERTADJUST_CENTER
:
722 case SDRTEXTVERTADJUST_BOTTOM
:
724 case SDRTEXTVERTADJUST_BLOCK
:
726 case SDRTEXTVERTADJUST_TOP
:
732 void VmlCommentExporter::EndShape( sal_Int32 nShapeElement
)
735 sax_fastparser::FSHelperPtr pVmlDrawing
= GetFS();
736 snprintf( pAnchor
, 100, "%" SAL_PRIdINT64
", %" SAL_PRIdINT64
", %" SAL_PRIdINT64
", %" SAL_PRIdINT64
", %" SAL_PRIdINT64
", %" SAL_PRIdINT64
", %" SAL_PRIdINT64
", %" SAL_PRIdINT64
,
737 sal_Int64(maFrom
.Left()), sal_Int64(maFrom
.Top()), sal_Int64(maFrom
.Right()), sal_Int64(maFrom
.Bottom()),
738 sal_Int64(maTo
.Left()), sal_Int64(maTo
.Top()), sal_Int64(maTo
.Right()), sal_Int64(maTo
.Bottom()) );
740 // Getting comment text alignments
741 const char* pVertAlign
= lcl_GetVertAlignFromItemSetChar(mpCaption
->GetMergedItemSet());
742 const char* pHorizAlign
= lcl_GetHorizAlignFromItemSetChar(mpCaption
->GetMergedItemSet());
744 pVmlDrawing
->startElement(FSNS(XML_x
, XML_ClientData
), XML_ObjectType
, "Note");
745 pVmlDrawing
->singleElement(FSNS(XML_x
, XML_MoveWithCells
));
746 pVmlDrawing
->singleElement(FSNS(XML_x
, XML_SizeWithCells
));
747 XclXmlUtils::WriteElement( pVmlDrawing
, FSNS( XML_x
, XML_Anchor
), pAnchor
);
748 XclXmlUtils::WriteElement( pVmlDrawing
, FSNS( XML_x
, XML_AutoFill
), "False" );
749 XclXmlUtils::WriteElement( pVmlDrawing
, FSNS( XML_x
, XML_TextVAlign
), pVertAlign
);
750 XclXmlUtils::WriteElement( pVmlDrawing
, FSNS( XML_x
, XML_TextHAlign
), pHorizAlign
);
751 XclXmlUtils::WriteElement( pVmlDrawing
, FSNS( XML_x
, XML_Row
), maScPos
.Row() );
752 XclXmlUtils::WriteElement( pVmlDrawing
, FSNS(XML_x
, XML_Column
), sal_Int32(maScPos
.Col()));
754 pVmlDrawing
->singleElement(FSNS(XML_x
, XML_Visible
));
755 pVmlDrawing
->endElement( FSNS( XML_x
, XML_ClientData
) );
757 VMLExport::EndShape( nShapeElement
);
760 void XclObjComment::SaveXml( XclExpXmlStream
& rStrm
)
762 VmlCommentExporter
aCommentExporter( rStrm
.GetCurrentStream(), maScPos
, mpCaption
, mbVisible
, maFrom
, maTo
);
763 aCommentExporter
.AddSdrObject( *mpCaption
);
766 // --- class XclObjDropDown ------------------------------------------
768 XclObjDropDown::XclObjDropDown( XclExpObjectManager
& rObjMgr
, const ScAddress
& rPos
, bool bFilt
) :
769 XclObj( rObjMgr
, EXC_OBJTYPE_DROPDOWN
, true ),
773 SetPrintable( false );
775 SetAutoLine( false );
776 nGrbit
|= 0x0100; // undocumented
777 mrEscherEx
.OpenContainer( ESCHER_SpContainer
);
778 mrEscherEx
.AddShape( ESCHER_ShpInst_HostControl
, ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
);
779 EscherPropertyContainer aPropOpt
;
780 aPropOpt
.AddOpt( ESCHER_Prop_LockAgainstGrouping
, 0x01040104 ); // bool field
781 aPropOpt
.AddOpt( ESCHER_Prop_FitTextToShape
, 0x00080008 ); // bool field
782 aPropOpt
.AddOpt( ESCHER_Prop_fNoFillHitTest
, 0x00010000 ); // bool field
783 aPropOpt
.AddOpt( ESCHER_Prop_fNoLineDrawDash
, 0x00080000 ); // bool field
784 aPropOpt
.AddOpt( ESCHER_Prop_fPrint
, 0x000A0000 ); // bool field
785 aPropOpt
.Commit( mrEscherEx
.GetStream() );
787 XclExpDffDropDownAnchor( rObjMgr
.GetRoot(), rPos
).WriteDffData( mrEscherEx
);
789 mrEscherEx
.AddAtom( 0, ESCHER_ClientData
); // OBJ record
790 mrEscherEx
.UpdateDffFragmentEnd();
791 mrEscherEx
.CloseContainer(); // ESCHER_SpContainer
793 // old size + ftSbs + ftLbsData
794 AddRecSize( 24 + 20 );
797 XclObjDropDown::~XclObjDropDown()
801 void XclObjDropDown::WriteSubRecs( XclExpStream
& rStrm
)
803 // ftSbs subrecord - Scroll bars (dummy)
804 rStrm
.StartRecord( EXC_ID_OBJSBS
, 20 );
805 rStrm
.WriteZeroBytes( 20 );
808 // ftLbsData subrecord - Listbox data
809 sal_uInt16 nDropDownFlags
= 0;
810 ::insert_value( nDropDownFlags
, EXC_OBJ_DROPDOWN_SIMPLE
, 0, 2 );
811 ::set_flag( nDropDownFlags
, EXC_OBJ_DROPDOWN_FILTERED
, bIsFiltered
);
812 rStrm
.StartRecord( EXC_ID_OBJLBSDATA
, 16 );
813 rStrm
<< sal_uInt32(0) << sal_uInt16(0) << sal_uInt16(0x0301) << sal_uInt16(0)
814 << nDropDownFlags
<< sal_uInt16( 20 ) << sal_uInt16( 130 );
818 // --- class XclTxo --------------------------------------------------
820 static sal_uInt8
lcl_GetHorAlignFromItemSet( const SfxItemSet
& rItemSet
)
822 sal_uInt8 nHorAlign
= EXC_OBJ_HOR_LEFT
;
824 switch( rItemSet
.Get( EE_PARA_JUST
).GetAdjust() )
826 case SvxAdjust::Left
: nHorAlign
= EXC_OBJ_HOR_LEFT
; break;
827 case SvxAdjust::Center
: nHorAlign
= EXC_OBJ_HOR_CENTER
; break;
828 case SvxAdjust::Right
: nHorAlign
= EXC_OBJ_HOR_RIGHT
; break;
829 case SvxAdjust::Block
: nHorAlign
= EXC_OBJ_HOR_JUSTIFY
; break;
835 static sal_uInt8
lcl_GetVerAlignFromItemSet( const SfxItemSet
& rItemSet
)
837 sal_uInt8 nVerAlign
= EXC_OBJ_VER_TOP
;
839 switch( rItemSet
.Get( SDRATTR_TEXT_VERTADJUST
).GetValue() )
841 case SDRTEXTVERTADJUST_TOP
: nVerAlign
= EXC_OBJ_VER_TOP
; break;
842 case SDRTEXTVERTADJUST_CENTER
: nVerAlign
= EXC_OBJ_VER_CENTER
; break;
843 case SDRTEXTVERTADJUST_BOTTOM
: nVerAlign
= EXC_OBJ_VER_BOTTOM
; break;
844 case SDRTEXTVERTADJUST_BLOCK
: nVerAlign
= EXC_OBJ_VER_JUSTIFY
; break;
850 XclTxo::XclTxo( const OUString
& rString
, sal_uInt16 nFontIx
) :
851 mpString( std::make_shared
<XclExpString
>( rString
) ),
852 mnRotation( EXC_OBJ_ORIENT_NONE
),
853 mnHorAlign( EXC_OBJ_HOR_LEFT
),
854 mnVerAlign( EXC_OBJ_VER_TOP
)
856 if( mpString
->Len() )
858 // If there is text, Excel *needs* the 2nd CONTINUE record with at least two format runs
859 mpString
->AppendFormat( 0, nFontIx
);
860 mpString
->AppendFormat( mpString
->Len(), EXC_FONT_APP
);
864 XclTxo::XclTxo( const XclExpRoot
& rRoot
, const SdrTextObj
& rTextObj
) :
865 mpString( XclExpStringHelper::CreateString( rRoot
, rTextObj
) ),
866 mnRotation( EXC_OBJ_ORIENT_NONE
),
867 mnHorAlign( EXC_OBJ_HOR_LEFT
),
868 mnVerAlign( EXC_OBJ_VER_TOP
)
870 // additional alignment and orientation items
871 const SfxItemSet
& rItemSet
= rTextObj
.GetMergedItemSet();
873 // horizontal alignment
874 SetHorAlign( lcl_GetHorAlignFromItemSet( rItemSet
) );
876 // vertical alignment
877 SetVerAlign( lcl_GetVerAlignFromItemSet( rItemSet
) );
880 Degree100 nAngle
= rTextObj
.GetRotateAngle();
881 if( (4500_deg100
< nAngle
) && (nAngle
< 13500_deg100
) )
882 mnRotation
= EXC_OBJ_ORIENT_90CCW
;
883 else if( (22500_deg100
< nAngle
) && (nAngle
< 31500_deg100
) )
884 mnRotation
= EXC_OBJ_ORIENT_90CW
;
886 mnRotation
= EXC_OBJ_ORIENT_NONE
;
889 XclTxo::XclTxo( const XclExpRoot
& rRoot
, const EditTextObject
& rEditObj
, SdrObject
* pCaption
) :
890 mpString( XclExpStringHelper::CreateString( rRoot
, rEditObj
) ),
891 mnRotation( EXC_OBJ_ORIENT_NONE
),
892 mnHorAlign( EXC_OBJ_HOR_LEFT
),
893 mnVerAlign( EXC_OBJ_VER_TOP
)
898 // Excel has one alignment per NoteObject while Calc supports
899 // one alignment per paragraph - use the first paragraph
900 // alignment (if set) as our overall alignment.
901 OUString
aParaText( rEditObj
.GetText( 0 ) );
902 if( !aParaText
.isEmpty() )
904 const SfxItemSet
& aSet( rEditObj
.GetParaAttribs( 0));
905 const SfxPoolItem
* pItem
= nullptr;
906 if( aSet
.GetItemState( EE_PARA_JUST
, true, &pItem
) == SfxItemState::SET
)
908 SvxAdjust eEEAlign
= static_cast< const SvxAdjustItem
& >( *pItem
).GetAdjust();
909 pCaption
->SetMergedItem( SvxAdjustItem( eEEAlign
, EE_PARA_JUST
) );
912 const SfxItemSet
& rItemSet
= pCaption
->GetMergedItemSet();
914 // horizontal alignment
915 SetHorAlign( lcl_GetHorAlignFromItemSet( rItemSet
) );
917 // vertical alignment
918 SetVerAlign( lcl_GetVerAlignFromItemSet( rItemSet
) );
920 // orientation alignment
921 const SvxWritingModeItem
& rItem
= rItemSet
.Get( SDRATTR_TEXTDIRECTION
);
922 if( rItem
.GetValue() == css::text::WritingMode_TB_RL
)
923 mnRotation
= EXC_OBJ_ORIENT_90CW
;
926 void XclTxo::SaveCont( XclExpStream
& rStrm
)
928 OSL_ENSURE( mpString
, "XclTxo::SaveCont - missing string" );
930 // #i96858# do not save existing string formatting if text is empty
931 sal_uInt16 nRunLen
= mpString
->IsEmpty() ? 0 : (8 * mpString
->GetFormatsCount());
933 sal_uInt16 nFlags
= 0;
934 ::insert_value( nFlags
, mnHorAlign
, 1, 3 );
935 ::insert_value( nFlags
, mnVerAlign
, 4, 3 );
937 rStrm
<< nFlags
<< mnRotation
;
938 rStrm
.WriteZeroBytes( 6 );
939 rStrm
<< mpString
->Len() << nRunLen
<< sal_uInt32( 0 );
942 void XclTxo::Save( XclExpStream
& rStrm
)
944 // Write the TXO part
945 ExcRecord::Save( rStrm
);
947 // CONTINUE records are only written if there is some text
948 if( mpString
->IsEmpty() )
951 // CONTINUE for character array
952 rStrm
.StartRecord( EXC_ID_CONT
, mpString
->GetBufferSize() + 1 );
953 rStrm
<< static_cast< sal_uInt8
>( mpString
->GetFlagField() & EXC_STRF_16BIT
); // only Unicode flag
954 mpString
->WriteBuffer( rStrm
);
957 // CONTINUE for formatting runs
958 rStrm
.StartRecord( EXC_ID_CONT
, 8 * mpString
->GetFormatsCount() );
959 const XclFormatRunVec
& rFormats
= mpString
->GetFormats();
960 for( const auto& rFormat
: rFormats
)
961 rStrm
<< rFormat
.mnChar
<< rFormat
.mnFontIdx
<< sal_uInt32( 0 );
965 sal_uInt16
XclTxo::GetNum() const
970 std::size_t XclTxo::GetLen() const
975 // --- class XclObjOle -------------------------------------------
977 XclObjOle::XclObjOle( XclExpObjectManager
& rObjMgr
, const SdrObject
& rObj
) :
978 XclObj( rObjMgr
, EXC_OBJTYPE_PICTURE
),
980 pRootStorage( rObjMgr
.GetRoot().GetRootStorage().get() )
984 XclObjOle::~XclObjOle()
988 void XclObjOle::WriteSubRecs( XclExpStream
& rStrm
)
990 // write only as embedded, not linked
991 OUString
aStorageName( "MBD" );
992 char aBuf
[ sizeof(sal_uInt32
) * 2 + 1 ];
993 // FIXME Eeek! Is this just a way to get a unique id?
994 sal_uInt32 nPictureId
= sal_uInt32(reinterpret_cast<sal_uIntPtr
>(this) >> 2);
995 sprintf( aBuf
, "%08X", static_cast< unsigned int >( nPictureId
) );
996 aStorageName
+= OUString::createFromAscii(aBuf
);
997 tools::SvRef
<SotStorage
> xOleStg
= pRootStorage
->OpenSotStorage( aStorageName
);
1001 uno::Reference
< embed::XEmbeddedObject
> xObj( static_cast<const SdrOle2Obj
&>(rOleObj
).GetObjRef() );
1005 // set version to "old" version, because it must be
1006 // saved in MS notation.
1008 const SvtFilterOptions
& rFltOpts
= SvtFilterOptions::Get();
1009 if( rFltOpts
.IsMath2MathType() )
1010 nFl
|= OLE_STARMATH_2_MATHTYPE
;
1012 if( rFltOpts
.IsWriter2WinWord() )
1013 nFl
|= OLE_STARWRITER_2_WINWORD
;
1015 if( rFltOpts
.IsCalc2Excel() )
1016 nFl
|= OLE_STARCALC_2_EXCEL
;
1018 if( rFltOpts
.IsImpress2PowerPoint() )
1019 nFl
|= OLE_STARIMPRESS_2_POWERPOINT
;
1021 SvxMSExportOLEObjects
aOLEExpFilt( nFl
);
1022 aOLEExpFilt
.ExportOLEObject( xObj
, *xOleStg
);
1024 // OBJCF subrecord, undocumented as usual
1025 rStrm
.StartRecord( EXC_ID_OBJCF
, 2 );
1026 rStrm
<< sal_uInt16(0x0002);
1029 // OBJFLAGS subrecord, undocumented as usual
1030 rStrm
.StartRecord( EXC_ID_OBJFLAGS
, 2 );
1031 sal_uInt16 nFlags
= EXC_OBJ_PIC_MANUALSIZE
;
1032 ::set_flag( nFlags
, EXC_OBJ_PIC_SYMBOL
, static_cast<const SdrOle2Obj
&>(rOleObj
).GetAspect() == embed::Aspects::MSOLE_ICON
);
1036 // OBJPICTFMLA subrecord, undocumented as usual
1037 XclExpString
aName( xOleStg
->GetUserName() );
1038 sal_uInt16 nPadLen
= static_cast<sal_uInt16
>(aName
.GetSize() & 0x01);
1039 sal_uInt16 nFmlaLen
= static_cast< sal_uInt16
>( 12 + aName
.GetSize() + nPadLen
);
1040 sal_uInt16 nSubRecLen
= nFmlaLen
+ 6;
1042 rStrm
.StartRecord( EXC_ID_OBJPICTFMLA
, nSubRecLen
);
1044 << sal_uInt16( 5 ) << sal_uInt32( 0 ) << sal_uInt8( 2 )
1045 << sal_uInt32( 0 ) << sal_uInt8( 3 )
1048 rStrm
<< sal_uInt8( 0 ); // pad byte
1049 rStrm
<< nPictureId
;
1053 void XclObjOle::Save( XclExpStream
& rStrm
)
1055 // content of this record
1056 XclObj::Save( rStrm
);
1059 // --- class XclObjAny -------------------------------------------
1061 XclObjAny::XclObjAny( XclExpObjectManager
& rObjMgr
, const Reference
< XShape
>& rShape
, ScDocument
* pDoc
)
1062 : XclObj( rObjMgr
, EXC_OBJTYPE_UNKNOWN
)
1068 XclObjAny::~XclObjAny()
1072 void XclObjAny::WriteSubRecs( XclExpStream
& rStrm
)
1074 if( mnObjType
== EXC_OBJTYPE_GROUP
)
1076 rStrm
<< EXC_ID_OBJGMO
<< sal_uInt16(2) << sal_uInt16(0);
1079 void XclObjAny::Save( XclExpStream
& rStrm
)
1081 if( mnObjType
== EXC_OBJTYPE_GROUP
)
1085 // content of this record
1086 XclObj::Save( rStrm
);
1089 // --- class ExcBof8_Base --------------------------------------------
1091 ExcBof8_Base::ExcBof8_Base()
1098 void XclObjAny::WriteFromTo( XclExpXmlStream
& rStrm
, const Reference
< XShape
>& rShape
, SCTAB nTab
)
1100 sax_fastparser::FSHelperPtr pDrawing
= rStrm
.GetCurrentStream();
1102 awt::Point aTopLeft
= rShape
->getPosition();
1103 awt::Size aSize
= rShape
->getSize();
1105 // There are a few cases where we must adjust these values
1106 // Do not adjust objects, which have rotation incorporated into their points
1107 // but report a rotation angle nevertheless.
1108 SdrObject
* pObj
= SdrObject::getSdrObjectFromXShape(rShape
);
1109 if (pObj
&& pObj
->GetObjIdentifier() != OBJ_LINE
&& pObj
->GetObjIdentifier() != OBJ_PLIN
1110 && pObj
->GetObjIdentifier() != OBJ_PATHLINE
&& pObj
->GetObjIdentifier() != OBJ_FREELINE
1111 && pObj
->GetObjIdentifier() != OBJ_PATHPLIN
)
1113 Degree100 nRotation
= NormAngle36000(pObj
->GetRotateAngle());
1116 sal_Int16 nHalfWidth
= aSize
.Width
/ 2;
1117 sal_Int16 nHalfHeight
= aSize
.Height
/ 2;
1119 // Center of bounding box of the rotated shape
1120 const auto aSnapRectCenter(pObj
->GetSnapRect().Center());
1121 aTopLeft
.X
= aSnapRectCenter
.X() - nHalfWidth
;
1122 aTopLeft
.Y
= aSnapRectCenter
.Y() - nHalfHeight
;
1124 // MSO changes the anchor positions at these angles and that does an extra 90 degrees
1125 // rotation on our shapes, so we output it in such position that MSO
1126 // can draw this shape correctly.
1127 if ((nRotation
> 4500_deg100
&& nRotation
<= 13500_deg100
) || (nRotation
> 22500_deg100
&& nRotation
<= 31500_deg100
))
1129 aTopLeft
.X
= aTopLeft
.X
- nHalfHeight
+ nHalfWidth
;
1130 aTopLeft
.Y
= aTopLeft
.Y
- nHalfWidth
+ nHalfHeight
;
1132 std::swap(aSize
.Width
, aSize
.Height
);
1137 tools::Rectangle
aLocation( aTopLeft
.X
, aTopLeft
.Y
, aTopLeft
.X
+ aSize
.Width
, aTopLeft
.Y
+ aSize
.Height
);
1138 ScRange aRange
= rStrm
.GetRoot().GetDoc().GetRange( nTab
, aLocation
);
1139 tools::Rectangle aRangeRect
= rStrm
.GetRoot().GetDoc().GetMMRect( aRange
.aStart
.Col(), aRange
.aStart
.Row(),
1140 aRange
.aEnd
.Col()-1, aRange
.aEnd
.Row()-1,
1143 pDrawing
->startElement(FSNS(XML_xdr
, XML_from
));
1144 XclXmlUtils::WriteElement( pDrawing
, FSNS( XML_xdr
, XML_col
), static_cast<sal_Int32
>(aRange
.aStart
.Col()) );
1145 XclXmlUtils::WriteElement( pDrawing
, FSNS( XML_xdr
, XML_colOff
),
1146 oox::drawingml::convertHmmToEmu( aLocation
.Left() - aRangeRect
.Left() ) );
1147 XclXmlUtils::WriteElement( pDrawing
, FSNS( XML_xdr
, XML_row
), static_cast<sal_Int32
>(aRange
.aStart
.Row()) );
1148 XclXmlUtils::WriteElement( pDrawing
, FSNS( XML_xdr
, XML_rowOff
),
1149 oox::drawingml::convertHmmToEmu( aLocation
.Top() - aRangeRect
.Top() ) );
1150 pDrawing
->endElement( FSNS( XML_xdr
, XML_from
) );
1152 pDrawing
->startElement(FSNS(XML_xdr
, XML_to
));
1153 XclXmlUtils::WriteElement( pDrawing
, FSNS( XML_xdr
, XML_col
), static_cast<sal_Int32
>(aRange
.aEnd
.Col()) );
1154 XclXmlUtils::WriteElement( pDrawing
, FSNS( XML_xdr
, XML_colOff
),
1155 oox::drawingml::convertHmmToEmu( aLocation
.Right() - aRangeRect
.Right() ) );
1156 XclXmlUtils::WriteElement( pDrawing
, FSNS( XML_xdr
, XML_row
), static_cast<sal_Int32
>(aRange
.aEnd
.Row()) );
1157 XclXmlUtils::WriteElement( pDrawing
, FSNS( XML_xdr
, XML_rowOff
),
1158 oox::drawingml::convertHmmToEmu( aLocation
.Bottom() - aRangeRect
.Bottom() ) );
1159 pDrawing
->endElement( FSNS( XML_xdr
, XML_to
) );
1162 void XclObjAny::WriteFromTo( XclExpXmlStream
& rStrm
, const XclObjAny
& rObj
)
1164 WriteFromTo( rStrm
, rObj
.GetShape(), rObj
.GetTab() );
1168 GetEditAs( const XclObjAny
& rObj
)
1170 if( const SdrObject
* pShape
= EscherEx::GetSdrObject( rObj
.GetShape() ) )
1172 switch( ScDrawLayer::GetAnchorType( *pShape
) )
1176 case SCA_CELL_RESIZE
:
1188 ScRefFlags
parseRange(const OUString
& rString
, ScRange
& rRange
, const ScDocument
& rDoc
)
1190 // start with the address convention set in the document
1191 formula::FormulaGrammar::AddressConvention eConv
= rDoc
.GetAddressConvention();
1192 ScRefFlags nResult
= rRange
.Parse(rString
, rDoc
, eConv
);
1193 if ( nResult
& ScRefFlags::VALID
)
1196 // try the default calc address convention
1197 nResult
= rRange
.Parse(rString
, rDoc
);
1198 if ( nResult
& ScRefFlags::VALID
)
1202 nResult
= rRange
.Parse(rString
, rDoc
, formula::FormulaGrammar::CONV_XL_A1
);
1203 if ( nResult
& ScRefFlags::VALID
)
1207 return rRange
.Parse(rString
, rDoc
, formula::FormulaGrammar::CONV_XL_R1C1
);
1210 ScRefFlags
parseAddress(const OUString
& rString
, ScAddress
& rAddress
, const ScDocument
& rDoc
)
1212 // start with the address convention set in the document
1213 formula::FormulaGrammar::AddressConvention eConv
= rDoc
.GetAddressConvention();
1214 ScRefFlags nResult
= rAddress
.Parse(rString
, rDoc
, eConv
);
1215 if ( nResult
& ScRefFlags::VALID
)
1218 // try the default calc address convention
1219 nResult
= rAddress
.Parse(rString
, rDoc
);
1220 if ( nResult
& ScRefFlags::VALID
)
1224 nResult
= rAddress
.Parse(rString
, rDoc
, formula::FormulaGrammar::CONV_XL_A1
);
1225 if ( nResult
& ScRefFlags::VALID
)
1229 return rAddress
.Parse(rString
, rDoc
, formula::FormulaGrammar::CONV_XL_R1C1
);
1232 void transformURL(const OUString
& rOldURL
, OUString
& rNewURL
, const ScDocument
& rDoc
)
1234 if (rOldURL
.startsWith("#"))
1236 // URL has to be decoded for escaped characters (%20)
1237 OUString aURL
= INetURLObject::decode( rOldURL
,
1238 INetURLObject::DecodeMechanism::WithCharset
);
1239 OUString aAddressString
= aURL
.copy(1);
1242 ScRefFlags nResult
= parseRange(aAddressString
, aRange
, rDoc
);
1243 if ( nResult
& ScRefFlags::VALID
)
1245 OUString aString
= aRange
.Format(rDoc
, nResult
, formula::FormulaGrammar::CONV_XL_OOX
);
1246 rNewURL
= "#" + aString
;
1252 nResult
= parseAddress(aAddressString
, aAddress
, rDoc
);
1253 if( nResult
& ScRefFlags::VALID
)
1255 OUString aString
= aAddress
.Format(nResult
, &rDoc
, formula::FormulaGrammar::CONV_XL_OOX
);
1256 rNewURL
= "#" + aString
;
1267 ScURLTransformer::ScURLTransformer(ScDocument
& rDoc
)
1272 OUString
ScURLTransformer::getTransformedString(const OUString
& rURL
) const
1275 transformURL(rURL
, aNewURL
, mrDoc
);
1279 bool ScURLTransformer::isExternalURL(const OUString
& rURL
) const
1281 return !rURL
.startsWith("#");
1284 void XclObjAny::SaveXml( XclExpXmlStream
& rStrm
)
1286 // ignore group shapes at the moment, we don't process them correctly
1287 // leading to ms2010 rejecting the content
1288 if( !mxShape
.is() || mxShape
->getShapeType() == "com.sun.star.drawing.GroupShape" )
1291 // Do not output any of the detective shapes and validation circles.
1292 SdrObject
* pObject
= SdrObject::getSdrObjectFromXShape(mxShape
);
1295 ScDocument
& rDoc
= rStrm
.GetRoot().GetDoc();
1296 ScDetectiveFunc
aDetFunc(rDoc
, mnScTab
);
1297 ScAddress aPosition
;
1298 ScRange aSourceRange
;
1300 ScDetectiveObjType eObjType
1301 = aDetFunc
.GetDetectiveObjectType(pObject
, mnScTab
, aPosition
, aSourceRange
, bRedLine
);
1303 if (eObjType
!= SC_DETOBJ_NONE
)
1307 sax_fastparser::FSHelperPtr pDrawing
= rStrm
.GetCurrentStream();
1309 ShapeExport
aDML(XML_xdr
, pDrawing
, nullptr, &rStrm
, drawingml::DOCUMENT_XLSX
);
1310 auto pURLTransformer
= std::make_shared
<ScURLTransformer
>(*mpDoc
);
1311 aDML
.SetURLTranslator(pURLTransformer
);
1313 pDrawing
->startElement( FSNS( XML_xdr
, XML_twoCellAnchor
), // OOXTODO: oneCellAnchor, absoluteAnchor
1314 XML_editAs
, GetEditAs( *this ) );
1315 Reference
< XPropertySet
> xPropSet( mxShape
, UNO_QUERY
);
1318 WriteFromTo( rStrm
, *this );
1319 aDML
.WriteShape( mxShape
);
1322 pDrawing
->singleElement( FSNS( XML_xdr
, XML_clientData
)
1323 // OOXTODO: XML_fLocksWithSheet
1324 // OOXTODO: XML_fPrintsWithSheet
1326 pDrawing
->endElement( FSNS( XML_xdr
, XML_twoCellAnchor
) );
1329 void ExcBof8_Base::SaveCont( XclExpStream
& rStrm
)
1331 rStrm
.DisableEncryption();
1332 rStrm
<< nVers
<< nDocType
<< nRupBuild
<< nRupYear
1333 << sal_uInt32(0)/*nFileHistory*/
1334 << sal_uInt32(0x06) /*nLowestBiffVer = Biff8*/;
1337 sal_uInt16
ExcBof8_Base::GetNum() const
1342 std::size_t ExcBof8_Base::GetLen() const
1347 // --- class ExcBof8 -------------------------------------------------
1354 // --- class ExcBofW8 ------------------------------------------------
1356 ExcBofW8::ExcBofW8()
1361 // --- class ExcBundlesheet8 -----------------------------------------
1363 ExcBundlesheet8::ExcBundlesheet8( const RootData
& rRootData
, SCTAB _nTab
) :
1364 ExcBundlesheetBase( rRootData
, static_cast<sal_uInt16
>(_nTab
) ),
1365 sUnicodeName( rRootData
.pER
->GetTabInfo().GetScTabName( _nTab
) )
1369 ExcBundlesheet8::ExcBundlesheet8( const OUString
& rString
) :
1370 sUnicodeName( rString
)
1374 void ExcBundlesheet8::SaveCont( XclExpStream
& rStrm
)
1376 m_nOwnPos
= rStrm
.GetSvStreamPos();
1377 // write dummy position, real position comes later
1378 rStrm
.DisableEncryption();
1379 rStrm
<< sal_uInt32(0);
1380 rStrm
.EnableEncryption();
1381 rStrm
<< nGrbit
<< GetName();
1384 std::size_t ExcBundlesheet8::GetLen() const
1385 { // Text max 255 chars
1386 return 8 + GetName().GetBufferSize();
1389 void ExcBundlesheet8::SaveXml( XclExpXmlStream
& rStrm
)
1392 rStrm
.CreateOutputStream(
1393 XclXmlUtils::GetStreamName( "xl/", "worksheets/sheet", nTab
+1),
1394 XclXmlUtils::GetStreamName( nullptr, "worksheets/sheet", nTab
+1),
1395 rStrm
.GetCurrentStream()->getOutputStream(),
1396 "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
1397 oox::getRelationship(Relationship::WORKSHEET
),
1400 rStrm
.GetCurrentStream()->singleElement( XML_sheet
,
1401 XML_name
, sUnicodeName
.toUtf8(),
1402 XML_sheetId
, OString::number( nTab
+1 ),
1403 XML_state
, nGrbit
== 0x0000 ? "visible" : "hidden",
1404 FSNS( XML_r
, XML_id
), sId
.toUtf8() );
1407 // --- class XclObproj -----------------------------------------------
1409 sal_uInt16
XclObproj::GetNum() const
1414 std::size_t XclObproj::GetLen() const
1419 // ---- class XclCodename --------------------------------------------
1421 XclCodename::XclCodename( const OUString
& r
) : aName( r
)
1425 void XclCodename::SaveCont( XclExpStream
& rStrm
)
1430 sal_uInt16
XclCodename::GetNum() const
1435 std::size_t XclCodename::GetLen() const
1437 return aName
.GetSize();
1440 // ---- Scenarios ----------------------------------------------------
1442 ExcEScenarioCell::ExcEScenarioCell( sal_uInt16 nC
, sal_uInt16 nR
, const OUString
& rTxt
) :
1445 sText( rTxt
, XclStrFlags::NONE
, 255 )
1449 void ExcEScenarioCell::WriteAddress( XclExpStream
& rStrm
) const
1451 rStrm
<< nRow
<< nCol
;
1454 void ExcEScenarioCell::WriteText( XclExpStream
& rStrm
) const
1459 void ExcEScenarioCell::SaveXml( XclExpXmlStream
& rStrm
) const
1461 rStrm
.GetCurrentStream()->singleElement( XML_inputCells
,
1462 // OOXTODO: XML_deleted,
1463 // OOXTODO: XML_numFmtId,
1464 XML_r
, XclXmlUtils::ToOString( rStrm
.GetRoot().GetDoc(), ScAddress( nCol
, nRow
, 0 ) ),
1465 // OOXTODO: XML_undone,
1466 XML_val
, XclXmlUtils::ToOString( sText
) );
1469 ExcEScenario::ExcEScenario( const XclExpRoot
& rRoot
, SCTAB nTab
)
1475 ScScenarioFlags nFlags
;
1477 ScDocument
& rDoc
= rRoot
.GetDoc();
1478 rDoc
.GetName(nTab
, aTmp
);
1480 sName
.Assign( sTmpName
, XclStrFlags::EightBitLength
);
1481 nRecLen
= 8 + sName
.GetBufferSize();
1483 rDoc
.GetScenarioData( nTab
, aTmp
, aDummyCol
, nFlags
);
1485 sComment
.Assign( sTmpComm
, XclStrFlags::NONE
, 255 );
1486 if( sComment
.Len() )
1487 nRecLen
+= sComment
.GetSize();
1488 bProtected
= (nFlags
& ScScenarioFlags::Protected
) != ScScenarioFlags::NONE
;
1490 sUserName
.Assign( rRoot
.GetUserName(), XclStrFlags::NONE
, 255 );
1491 nRecLen
+= sUserName
.GetSize();
1493 const ScRangeList
* pRList
= rDoc
.GetScenarioRanges( nTab
);
1497 bool bContLoop
= true;
1503 for( size_t nRange
= 0; (nRange
< pRList
->size()) && bContLoop
; nRange
++ )
1505 const ScRange
& rRange
= (*pRList
)[nRange
];
1506 for( nRow
= rRange
.aStart
.Row(); (nRow
<= rRange
.aEnd
.Row()) && bContLoop
; nRow
++ )
1507 for( nCol
= rRange
.aStart
.Col(); (nCol
<= rRange
.aEnd
.Col()) && bContLoop
; nCol
++ )
1509 if( rDoc
.HasValueData( nCol
, nRow
, nTab
) )
1511 fVal
= rDoc
.GetValue( nCol
, nRow
, nTab
);
1512 sText
= ::rtl::math::doubleToUString( fVal
,
1513 rtl_math_StringFormat_Automatic
,
1514 rtl_math_DecimalPlaces_Max
,
1515 ScGlobal::getLocaleData().getNumDecimalSep()[0],
1519 sText
= rDoc
.GetString(nCol
, nRow
, nTab
);
1520 bContLoop
= Append( static_cast<sal_uInt16
>(nCol
),
1521 static_cast<sal_uInt16
>(nRow
), sText
);
1526 bool ExcEScenario::Append( sal_uInt16 nCol
, sal_uInt16 nRow
, const OUString
& rTxt
)
1528 if( aCells
.size() == EXC_SCEN_MAXCELL
)
1531 ExcEScenarioCell
aCell(nCol
, nRow
, rTxt
);
1532 aCells
.push_back(aCell
);
1533 nRecLen
+= 6 + aCell
.GetStringBytes(); // 4 bytes address, 2 bytes ifmt
1537 void ExcEScenario::SaveCont( XclExpStream
& rStrm
)
1539 sal_uInt16 count
= aCells
.size();
1541 rStrm
<< count
// number of cells
1542 << sal_uInt8(bProtected
) // fProtection
1543 << sal_uInt8(0) // fHidden
1544 << static_cast<sal_uInt8
>(sName
.Len()) // length of scen name
1545 << static_cast<sal_uInt8
>(sComment
.Len()) // length of comment
1546 << static_cast<sal_uInt8
>(sUserName
.Len()); // length of user name
1547 sName
.WriteFlagField( rStrm
);
1548 sName
.WriteBuffer( rStrm
);
1552 if( sComment
.Len() )
1555 for( const auto& rCell
: aCells
)
1556 rCell
.WriteAddress( rStrm
); // pos of cell
1557 for( const auto& rCell
: aCells
)
1558 rCell
.WriteText( rStrm
); // string content
1559 rStrm
.SetSliceSize( 2 );
1560 rStrm
.WriteZeroBytes( 2 * count
); // date format
1563 sal_uInt16
ExcEScenario::GetNum() const
1568 std::size_t ExcEScenario::GetLen() const
1573 void ExcEScenario::SaveXml( XclExpXmlStream
& rStrm
)
1575 sax_fastparser::FSHelperPtr
& rWorkbook
= rStrm
.GetCurrentStream();
1576 rWorkbook
->startElement( XML_scenario
,
1577 XML_name
, XclXmlUtils::ToOString( sName
).getStr(),
1578 XML_locked
, ToPsz( bProtected
),
1579 // OOXTODO: XML_hidden,
1580 XML_count
, OString::number( aCells
.size() ).getStr(),
1581 XML_user
, XESTRING_TO_PSZ( sUserName
),
1582 XML_comment
, XESTRING_TO_PSZ( sComment
) );
1584 for( const auto& rCell
: aCells
)
1585 rCell
.SaveXml( rStrm
);
1587 rWorkbook
->endElement( XML_scenario
);
1590 ExcEScenarioManager::ExcEScenarioManager( const XclExpRoot
& rRoot
, SCTAB nTab
) :
1593 ScDocument
& rDoc
= rRoot
.GetDoc();
1594 if( rDoc
.IsScenario( nTab
) )
1597 SCTAB nFirstTab
= nTab
+ 1;
1598 SCTAB nNewTab
= nFirstTab
;
1600 while( rDoc
.IsScenario( nNewTab
) )
1602 aScenes
.emplace_back( rRoot
, nNewTab
);
1604 if( rDoc
.IsActiveScenario( nNewTab
) )
1605 nActive
= static_cast<sal_uInt16
>(nNewTab
- nFirstTab
);
1610 ExcEScenarioManager::~ExcEScenarioManager()
1614 void ExcEScenarioManager::SaveCont( XclExpStream
& rStrm
)
1616 rStrm
<< static_cast<sal_uInt16
>(aScenes
.size()) // number of scenarios
1617 << nActive
// active scen
1618 << nActive
// last displayed
1619 << sal_uInt16(0); // reference areas
1622 void ExcEScenarioManager::Save( XclExpStream
& rStrm
)
1624 if( !aScenes
.empty() )
1625 ExcRecord::Save( rStrm
);
1627 for( ExcEScenario
& rScenario
: aScenes
)
1628 rScenario
.Save( rStrm
);
1631 void ExcEScenarioManager::SaveXml( XclExpXmlStream
& rStrm
)
1633 if( aScenes
.empty() )
1636 sax_fastparser::FSHelperPtr
& rWorkbook
= rStrm
.GetCurrentStream();
1637 rWorkbook
->startElement( XML_scenarios
,
1638 XML_current
, OString::number( nActive
),
1639 XML_show
, OString::number( nActive
)
1640 // OOXTODO: XML_sqref
1643 for( ExcEScenario
& rScenario
: aScenes
)
1644 rScenario
.SaveXml( rStrm
);
1646 rWorkbook
->endElement( XML_scenarios
);
1649 sal_uInt16
ExcEScenarioManager::GetNum() const
1654 std::size_t ExcEScenarioManager::GetLen() const
1661 struct XclExpTabProtectOption
1663 ScTableProtection::Option eOption
;
1669 XclExpSheetProtectOptions::XclExpSheetProtectOptions( const XclExpRoot
& rRoot
, SCTAB nTab
) :
1670 XclExpRecord( 0x0867, 23 )
1672 static const XclExpTabProtectOption aTable
[] =
1674 { ScTableProtection::OBJECTS
, 0x0001 },
1675 { ScTableProtection::SCENARIOS
, 0x0002 },
1676 { ScTableProtection::FORMAT_CELLS
, 0x0004 },
1677 { ScTableProtection::FORMAT_COLUMNS
, 0x0008 },
1678 { ScTableProtection::FORMAT_ROWS
, 0x0010 },
1679 { ScTableProtection::INSERT_COLUMNS
, 0x0020 },
1680 { ScTableProtection::INSERT_ROWS
, 0x0040 },
1681 { ScTableProtection::INSERT_HYPERLINKS
, 0x0080 },
1683 { ScTableProtection::DELETE_COLUMNS
, 0x0100 },
1684 { ScTableProtection::DELETE_ROWS
, 0x0200 },
1685 { ScTableProtection::SELECT_LOCKED_CELLS
, 0x0400 },
1686 { ScTableProtection::SORT
, 0x0800 },
1687 { ScTableProtection::AUTOFILTER
, 0x1000 },
1688 { ScTableProtection::PIVOT_TABLES
, 0x2000 },
1689 { ScTableProtection::SELECT_UNLOCKED_CELLS
, 0x4000 },
1691 { ScTableProtection::NONE
, 0x0000 }
1695 const ScTableProtection
* pProtect
= rRoot
.GetDoc().GetTabProtection(nTab
);
1699 for (int i
= 0; aTable
[i
].nMask
!= 0x0000; ++i
)
1701 if ( pProtect
->isOptionEnabled(aTable
[i
].eOption
) )
1702 mnOptions
|= aTable
[i
].nMask
;
1706 void XclExpSheetProtectOptions::WriteBody( XclExpStream
& rStrm
)
1708 sal_uInt16 nBytes
= 0x0867;
1711 for (int i
= 0; i
< 9; ++i
)
1712 rStrm
<< static_cast<unsigned char>(0);
1719 rStrm
<< nBytes
<< nBytes
;
1726 XclExpSheetEnhancedProtection::XclExpSheetEnhancedProtection( const XclExpRoot
& rRoot
,
1727 const ScEnhancedProtection
& rProt
) :
1728 XclExpRecord( 0x0868 ),
1730 maEnhancedProtection( rProt
)
1734 void XclExpSheetEnhancedProtection::WriteBody( XclExpStream
& rStrm
)
1736 sal_uInt16
const nRecordType
= 0x0868;
1737 rStrm
<< nRecordType
; // frtHeader rt
1738 rStrm
.WriteZeroBytesToRecord(10); // frtHeader unused
1739 rStrm
<< EXC_ISFPROTECTION
; // isf
1740 rStrm
.WriteZeroBytesToRecord(5); // reserved1 (1 bytes) and reserved2 (4 bytes)
1743 if (maEnhancedProtection
.maRangeList
.is())
1744 mrRoot
.GetAddressConverter().ConvertRangeList( aRefs
, *maEnhancedProtection
.maRangeList
, false);
1745 sal_uInt16 nCref
= ulimit_cast
<sal_uInt16
>(aRefs
.size());
1746 rStrm
<< nCref
; // cref
1747 rStrm
.WriteZeroBytesToRecord(6); // cbFeatData if EXC_ISFFEC2 (4 bytes) and reserved3 (2 bytes)
1748 aRefs
.Write( rStrm
, true, nCref
); // refs
1750 // FeatProtection structure
1751 rStrm
<< maEnhancedProtection
.mnAreserved
; // 1 bit A and 31 bits reserved
1752 rStrm
<< maEnhancedProtection
.mnPasswordVerifier
; // wPassword
1753 rStrm
<< XclExpString( maEnhancedProtection
.maTitle
); // stTitle
1754 bool bSDContainer
= ((maEnhancedProtection
.mnAreserved
& 0x00000001) == 0x00000001);
1755 sal_uInt32 nCbSD
= maEnhancedProtection
.maSecurityDescriptor
.size();
1756 SAL_WARN_IF( bSDContainer
&& nCbSD
< 20, "sc.filter",
1757 "XclExpSheetEnhancedProtection A flag indicates container but cbSD < 20");
1758 SAL_WARN_IF( !bSDContainer
&& nCbSD
> 0, "sc.filter",
1759 "XclExpSheetEnhancedProtection A flag indicates no container but cbSD > 0");
1763 rStrm
.Write( &maEnhancedProtection
.maSecurityDescriptor
.front(), nCbSD
);
1767 void XclCalccount::SaveCont( XclExpStream
& rStrm
)
1772 XclCalccount::XclCalccount( const ScDocument
& rDoc
)
1774 nCount
= rDoc
.GetDocOptions().GetIterCount();
1777 sal_uInt16
XclCalccount::GetNum() const
1782 std::size_t XclCalccount::GetLen() const
1787 void XclCalccount::SaveXml( XclExpXmlStream
& rStrm
)
1789 rStrm
.WriteAttributes(XML_iterateCount
, OUString::number(nCount
));
1792 void XclIteration::SaveCont( XclExpStream
& rStrm
)
1797 XclIteration::XclIteration( const ScDocument
& rDoc
)
1799 nIter
= rDoc
.GetDocOptions().IsIter()? 1 : 0;
1802 sal_uInt16
XclIteration::GetNum() const
1807 std::size_t XclIteration::GetLen() const
1812 void XclIteration::SaveXml( XclExpXmlStream
& rStrm
)
1814 rStrm
.WriteAttributes(XML_iterate
, ToPsz(nIter
== 1));
1817 void XclDelta::SaveCont( XclExpStream
& rStrm
)
1822 XclDelta::XclDelta( const ScDocument
& rDoc
)
1824 fDelta
= rDoc
.GetDocOptions().GetIterEps();
1827 sal_uInt16
XclDelta::GetNum() const
1832 std::size_t XclDelta::GetLen() const
1837 void XclDelta::SaveXml( XclExpXmlStream
& rStrm
)
1839 rStrm
.WriteAttributes(XML_iterateDelta
, OUString::number(fDelta
));
1842 XclExpFileEncryption::XclExpFileEncryption( const XclExpRoot
& rRoot
) :
1843 XclExpRecord(0x002F, 54),
1848 XclExpFileEncryption::~XclExpFileEncryption()
1852 void XclExpFileEncryption::WriteBody( XclExpStream
& rStrm
)
1854 // 0x0000 - neither standard nor strong encryption
1855 // 0x0001 - standard or strong encryption
1856 rStrm
<< static_cast<sal_uInt16
>(0x0001);
1858 // 0x0000 - non standard encryption
1859 // 0x0001 - standard encryption
1860 sal_uInt16 nStdEnc
= 0x0001;
1861 rStrm
<< nStdEnc
<< nStdEnc
;
1863 sal_uInt8 pnDocId
[16];
1864 sal_uInt8 pnSalt
[16];
1865 sal_uInt8 pnSaltHash
[16];
1866 XclExpEncrypterRef xEnc
= std::make_shared
<XclExpBiff8Encrypter
>(mrRoot
);
1867 xEnc
->GetDocId(pnDocId
);
1868 xEnc
->GetSalt(pnSalt
);
1869 xEnc
->GetSaltDigest(pnSaltHash
);
1871 rStrm
.Write(pnDocId
, 16);
1872 rStrm
.Write(pnSalt
, 16);
1873 rStrm
.Write(pnSaltHash
, 16);
1875 rStrm
.SetEncrypter(xEnc
);
1878 XclExpInterfaceHdr::XclExpInterfaceHdr( sal_uInt16 nCodePage
) :
1879 XclExpUInt16Record( EXC_ID_INTERFACEHDR
, nCodePage
)
1883 void XclExpInterfaceHdr::WriteBody( XclExpStream
& rStrm
)
1885 rStrm
.DisableEncryption();
1886 rStrm
<< GetValue();
1889 XclExpInterfaceEnd::XclExpInterfaceEnd() :
1890 XclExpRecord(0x00E2, 0) {}
1892 XclExpInterfaceEnd::~XclExpInterfaceEnd() {}
1894 void XclExpInterfaceEnd::WriteBody( XclExpStream
& rStrm
)
1896 // Don't forget to re-enable encryption.
1897 rStrm
.EnableEncryption();
1900 XclExpWriteAccess::XclExpWriteAccess() :
1901 XclExpRecord(0x005C, 112)
1905 XclExpWriteAccess::~XclExpWriteAccess()
1909 void XclExpWriteAccess::WriteBody( XclExpStream
& rStrm
)
1911 static const sal_uInt8 aData
[] = {
1912 0x04, 0x00, 0x00, 'C', 'a', 'l', 'c', 0x20,
1913 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1914 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1915 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1916 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1917 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1918 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1919 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1920 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1921 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1922 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1923 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1924 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1925 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
1927 for (std::size_t i
= 0; i
< sizeof(aData
); ++i
)
1931 XclExpFileSharing::XclExpFileSharing( const XclExpRoot
& rRoot
, sal_uInt16 nPasswordHash
, bool bRecommendReadOnly
) :
1932 XclExpRecord( EXC_ID_FILESHARING
),
1933 mnPasswordHash( nPasswordHash
),
1934 mbRecommendReadOnly( bRecommendReadOnly
)
1936 if( rRoot
.GetBiff() <= EXC_BIFF5
)
1937 maUserName
.AssignByte( rRoot
.GetUserName(), rRoot
.GetTextEncoding(), XclStrFlags::EightBitLength
);
1939 maUserName
.Assign( rRoot
.GetUserName() );
1942 void XclExpFileSharing::Save( XclExpStream
& rStrm
)
1944 if( (mnPasswordHash
!= 0) || mbRecommendReadOnly
)
1945 XclExpRecord::Save( rStrm
);
1948 void XclExpFileSharing::WriteBody( XclExpStream
& rStrm
)
1950 rStrm
<< sal_uInt16( mbRecommendReadOnly
? 1 : 0 ) << mnPasswordHash
<< maUserName
;
1953 XclExpProt4Rev::XclExpProt4Rev() :
1954 XclExpRecord(0x01AF, 2)
1958 XclExpProt4Rev::~XclExpProt4Rev()
1962 void XclExpProt4Rev::WriteBody( XclExpStream
& rStrm
)
1964 rStrm
<< static_cast<sal_uInt16
>(0x0000);
1967 XclExpProt4RevPass::XclExpProt4RevPass() :
1968 XclExpRecord(0x01BC, 2)
1972 XclExpProt4RevPass::~XclExpProt4RevPass()
1976 void XclExpProt4RevPass::WriteBody( XclExpStream
& rStrm
)
1978 rStrm
<< static_cast<sal_uInt16
>(0x0000);
1981 const sal_uInt8 nDataRecalcId
[] = {
1982 0xC1, 0x01, 0x00, 0x00, 0x54, 0x8D, 0x01, 0x00
1985 XclExpRecalcId::XclExpRecalcId() :
1986 XclExpDummyRecord(0x01C1, nDataRecalcId
, sizeof(nDataRecalcId
))
1990 const sal_uInt8 nDataBookExt
[] = {
1991 0x63, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1992 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1996 XclExpBookExt::XclExpBookExt() :
1997 XclExpDummyRecord(0x0863, nDataBookExt
, sizeof(nDataBookExt
))
2001 XclRefmode::XclRefmode( const ScDocument
& rDoc
) :
2002 XclExpBoolRecord( 0x000F, rDoc
.GetAddressConvention() != formula::FormulaGrammar::CONV_XL_R1C1
)
2006 void XclRefmode::SaveXml( XclExpXmlStream
& rStrm
)
2008 rStrm
.WriteAttributes(XML_refMode
, GetBool() ? "A1" : "R1C1");
2011 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */