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 <o3tl/sprintf.hxx>
21 #include <svx/sdtaitm.hxx>
22 #include <svx/svdotext.hxx>
23 #include <editeng/editobj.hxx>
24 #include <svx/svdoole2.hxx>
25 #include <sot/storage.hxx>
26 #include <svl/itemset.hxx>
27 #include <svx/svdocapt.hxx>
28 #include <svx/unoapi.hxx>
29 #include <editeng/writingmodeitem.hxx>
30 #include <tools/urlobj.hxx>
32 #include <rtl/math.hxx>
34 #include <sal/log.hxx>
35 #include <drwlayer.hxx>
39 #include <xcl97rec.hxx>
40 #include <xcl97esc.hxx>
41 #include <xeescher.hxx>
42 #include <xehelper.hxx>
44 #include <xlcontent.hxx>
46 #include <unotools/fltrcfg.hxx>
47 #include <editeng/adjustitem.hxx>
48 #include <editeng/eeitem.hxx>
49 #include <filter/msfilter/msoleexp.hxx>
51 #include <unotools/localedatawrapper.hxx>
55 #include <document.hxx>
56 #include <rangelst.hxx>
57 #include <docoptio.hxx>
58 #include <tabprotection.hxx>
60 #include <com/sun/star/embed/Aspects.hpp>
61 #include <com/sun/star/chart/XChartDocument.hpp>
62 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
63 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
64 #include <com/sun/star/chart2/XChartDocument.hpp>
66 #include <sax/fastattribs.hxx>
67 #include <oox/token/tokens.hxx>
68 #include <oox/token/namespaces.hxx>
69 #include <oox/token/relationship.hxx>
70 #include <oox/export/shapes.hxx>
71 #include <oox/export/utils.hxx>
72 #include <oox/export/vmlexport.hxx>
73 #include <detfunc.hxx>
77 using namespace ::com::sun::star
;
78 using ::com::sun::star::uno::Reference
;
79 using ::com::sun::star::uno::UNO_QUERY
;
80 using ::com::sun::star::beans::XPropertySet
;
81 using ::com::sun::star::drawing::XShape
;
82 using ::oox::drawingml::ShapeExport
;
83 using ::oox::vml::VMLExport
;
86 XclExpObjList::XclExpObjList( const XclExpRoot
& rRoot
, XclEscherEx
& rEscherEx
) :
88 mnScTab( rRoot
.GetCurrScTab() ),
89 mrEscherEx( rEscherEx
)
91 pMsodrawingPerSheet
.reset( new XclExpMsoDrawing( rEscherEx
) );
92 // open the DGCONTAINER and the patriarch group shape
93 mrEscherEx
.OpenContainer( ESCHER_DgContainer
);
94 tools::Rectangle
aRect( 0, 0, 0, 0 );
95 mrEscherEx
.EnterGroup( &aRect
);
96 mrEscherEx
.UpdateDffFragmentEnd();
99 XclExpObjList::~XclExpObjList()
102 pMsodrawingPerSheet
.reset();
103 pSolverContainer
.reset();
106 sal_uInt16
XclExpObjList::Add( std::unique_ptr
<XclObj
> pObj
)
108 OSL_ENSURE( maObjs
.size() < 0xFFFF, "XclExpObjList::Add: too much for Xcl" );
110 size_t nSize
= maObjs
.size();
112 if ( nSize
< 0xFFFF )
114 pObj
->SetId( nSize
+1 );
115 pObj
->SetTab( mnScTab
);
116 maObjs
.push_back(std::move(pObj
));
127 std::unique_ptr
<XclObj
> XclExpObjList::pop_back ()
129 auto ret
= std::move(maObjs
.back());
134 void XclExpObjList::EndSheet()
136 // Is there still something in the stream? -> The solver container
137 if( mrEscherEx
.HasPendingDffData() )
138 pSolverContainer
.reset( new XclExpMsoDrawing( mrEscherEx
) );
140 // close the DGCONTAINER created by XclExpObjList ctor MSODRAWING
141 mrEscherEx
.CloseContainer();
144 void XclExpObjList::Save( XclExpStream
& rStrm
)
146 //! Escher must be written, even if there are no objects
147 pMsodrawingPerSheet
->Save( rStrm
);
149 for ( const auto& rxObj
: maObjs
)
150 rxObj
->Save( rStrm
);
152 if( pSolverContainer
)
153 pSolverContainer
->Save( rStrm
);
158 bool IsFormControlObject( const XclObj
*rObj
)
160 switch( rObj
->GetObjType() )
162 case EXC_OBJTYPE_CHECKBOX
:
163 case EXC_OBJTYPE_BUTTON
:
170 bool IsVmlObject( const XclObj
*rObj
)
172 switch( rObj
->GetObjType() )
174 case EXC_OBJTYPE_NOTE
:
181 sal_Int32
GetVmlObjectCount( XclExpObjList
& rList
)
183 return static_cast<sal_Int32
>(std::count_if(rList
.begin(), rList
.end(),
184 [](const std::unique_ptr
<XclObj
>& rxObj
) { return IsVmlObject( rxObj
.get() ) || IsFormControlObject( rxObj
.get() ); }));
187 bool IsValidObject( const XclObj
& rObj
)
189 if (rObj
.GetObjType() == EXC_OBJTYPE_CHART
)
191 // Chart object. Make sure it's a valid chart object. We skip
192 // invalid chart objects from exporting to prevent Excel from
193 // complaining on load.
195 const XclExpChartObj
& rChartObj
= static_cast<const XclExpChartObj
&>(rObj
);
196 uno::Reference
<chart2::XChartDocument
> xChartDoc(rChartObj
.GetChartDoc(), uno::UNO_QUERY
);
200 uno::Reference
<chart2::XDiagram
> xDiagram
= xChartDoc
->getFirstDiagram();
204 uno::Reference
<chart2::XCoordinateSystemContainer
> xCooSysContainer(xDiagram
, uno::UNO_QUERY
);
205 if (!xCooSysContainer
.is())
208 const uno::Sequence
<uno::Reference
<chart2::XCoordinateSystem
>> xCooSysSeq
= xCooSysContainer
->getCoordinateSystems();
209 for (const auto& rCooSys
: xCooSysSeq
)
211 Reference
<chart2::XChartTypeContainer
> xChartTypeCont(rCooSys
, uno::UNO_QUERY
);
212 if (!xChartTypeCont
.is())
215 uno::Sequence
<uno::Reference
<chart2::XChartType
>> xChartTypeSeq
= xChartTypeCont
->getChartTypes();
216 if (!xChartTypeSeq
.hasElements())
217 // No chart type. Not good.
225 void SaveDrawingMLObjects( XclExpObjList
& rList
, XclExpXmlStream
& rStrm
)
227 std::vector
<XclObj
*> aList
;
228 // do not add objects to the list that are in the group,
229 // because the group already contains them. For this, count
230 // the next skipped objects, i.e. objects of a group,
231 // including objects of its subgroups
233 for (const auto& rxObj
: rList
)
235 // FIXME: Can DrawingML objects be grouped with VML or not valid objects?
236 if (IsVmlObject(rxObj
.get()) || !IsValidObject(*rxObj
))
240 aList
.push_back(rxObj
.get());
244 XclObjAny
* pObj
= nullptr;
245 if (rxObj
->GetObjType() == 0) // group (it can be a subgroup)
246 pObj
= dynamic_cast<XclObjAny
*>(rxObj
.get());
249 css::uno::Reference
<css::drawing::XShapes
> xShapes(pObj
->GetShape(), UNO_QUERY
);
252 // skip (also) the objects of this group
253 nSkipObj
+= xShapes
->getCount();
261 sal_Int32 nDrawing
= drawingml::DrawingML::getNewDrawingUniqueId();
263 sax_fastparser::FSHelperPtr pDrawing
= rStrm
.CreateOutputStream(
264 XclXmlUtils::GetStreamName( "xl/", "drawings/drawing", nDrawing
),
265 XclXmlUtils::GetStreamName( "../", "drawings/drawing", nDrawing
),
266 rStrm
.GetCurrentStream()->getOutputStream(),
267 "application/vnd.openxmlformats-officedocument.drawing+xml",
268 oox::getRelationship(Relationship::DRAWING
),
271 rStrm
.GetCurrentStream()->singleElement(XML_drawing
, FSNS(XML_r
, XML_id
), sId
.toUtf8());
273 rStrm
.PushStream( pDrawing
);
274 pDrawing
->startElement( FSNS( XML_xdr
, XML_wsDr
),
275 FSNS(XML_xmlns
, XML_xdr
), rStrm
.getNamespaceURL(OOX_NS(dmlSpreadDr
)).toUtf8(),
276 FSNS(XML_xmlns
, XML_a
), rStrm
.getNamespaceURL(OOX_NS(dml
)).toUtf8(),
277 FSNS(XML_xmlns
, XML_r
), rStrm
.getNamespaceURL(OOX_NS(officeRel
)).toUtf8() );
279 sal_Int32 nShapeId
= 1000; // unique id of the shape inside one worksheet (not the whole document)
280 for (const auto& rpObj
: aList
)
283 if ( IsFormControlObject( rpObj
) )
285 XclExpTbxControlObj
* pXclExpTbxControlObj
= dynamic_cast<XclExpTbxControlObj
*>(rpObj
);
286 if (pXclExpTbxControlObj
)
288 pXclExpTbxControlObj
->setShapeId(++nShapeId
);
292 rpObj
->SaveXml(rStrm
);
295 pDrawing
->endElement( FSNS( XML_xdr
, XML_wsDr
) );
300 void SaveFormControlObjects(XclExpObjList
& rList
, XclExpXmlStream
& rStrm
)
302 bool hasControls
= false;
303 for (const auto& rxObj
: rList
)
305 if (IsFormControlObject(rxObj
.get()))
317 sax_fastparser::FSHelperPtr
& rWorksheet
= rStrm
.GetCurrentStream();
319 rWorksheet
->startElement(FSNS(XML_mc
, XML_AlternateContent
),
320 FSNS(XML_xmlns
, XML_mc
), rStrm
.getNamespaceURL(OOX_NS(mce
)).toUtf8());
321 rWorksheet
->startElement(FSNS(XML_mc
, XML_Choice
), XML_Requires
, "x14");
322 rWorksheet
->startElement(XML_controls
);
324 for (const auto& rxObj
: rList
)
326 if (IsFormControlObject(rxObj
.get()))
328 XclExpTbxControlObj
* pXclExpTbxControlObj
= dynamic_cast<XclExpTbxControlObj
*>(rxObj
.get());
329 if (pXclExpTbxControlObj
)
331 const OUString aIdFormControlPr
= pXclExpTbxControlObj
->SaveControlPropertiesXml(rStrm
);
332 pXclExpTbxControlObj
->SaveSheetXml(rStrm
, aIdFormControlPr
);
337 rWorksheet
->endElement(XML_controls
);
338 rWorksheet
->endElement(FSNS(XML_mc
, XML_Choice
));
339 rWorksheet
->endElement(FSNS(XML_mc
, XML_AlternateContent
));
342 void SaveVmlObjects( XclExpObjList
& rList
, XclExpXmlStream
& rStrm
)
344 if( GetVmlObjectCount( rList
) == 0 )
347 sal_Int32 nDrawing
= drawingml::DrawingML::getNewVMLUniqueId();
349 sax_fastparser::FSHelperPtr pVmlDrawing
= rStrm
.CreateOutputStream(
350 XclXmlUtils::GetStreamName( "xl/", "drawings/vmlDrawing", nDrawing
),
351 XclXmlUtils::GetStreamName( "../", "drawings/vmlDrawing", nDrawing
),
352 rStrm
.GetCurrentStream()->getOutputStream(),
353 "application/vnd.openxmlformats-officedocument.vmlDrawing",
354 oox::getRelationship(Relationship::VMLDRAWING
),
357 rStrm
.GetCurrentStream()->singleElement(XML_legacyDrawing
, FSNS(XML_r
, XML_id
), sId
.toUtf8());
359 rStrm
.PushStream( pVmlDrawing
);
360 pVmlDrawing
->write("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
361 pVmlDrawing
->startElement( XML_xml
,
362 FSNS(XML_xmlns
, XML_v
), rStrm
.getNamespaceURL(OOX_NS(vml
)).toUtf8(),
363 FSNS(XML_xmlns
, XML_o
), rStrm
.getNamespaceURL(OOX_NS(vmlOffice
)).toUtf8(),
364 FSNS(XML_xmlns
, XML_x
), rStrm
.getNamespaceURL(OOX_NS(vmlExcel
)).toUtf8(),
365 FSNS(XML_xmlns
, XML_w10
), rStrm
.getNamespaceURL(OOX_NS(vmlWord
)).toUtf8() );
367 for ( const auto& rxObj
: rList
)
369 if (IsFormControlObject(rxObj
.get()))
371 auto pFormControlObject
= dynamic_cast<XclExpTbxControlObj
*>(rxObj
.get());
372 if (pFormControlObject
)
374 pFormControlObject
->SaveVml(rStrm
);
378 if( !IsVmlObject( rxObj
.get() ) )
380 rxObj
->SaveXml( rStrm
);
383 pVmlDrawing
->endElement( XML_xml
);
390 void XclExpObjList::SaveXml( XclExpXmlStream
& rStrm
)
392 if( pSolverContainer
)
393 pSolverContainer
->SaveXml( rStrm
);
398 SaveDrawingMLObjects( *this, rStrm
);
399 SaveVmlObjects( *this, rStrm
);
400 SaveFormControlObjects( *this, rStrm
);
403 // --- class XclObj --------------------------------------------------
405 XclObj::XclObj( XclExpObjectManager
& rObjMgr
, sal_uInt16 nObjType
, bool bOwnEscher
) :
406 XclExpRecord( EXC_ID_OBJ
, 26 ),
407 mrEscherEx( rObjMgr
.GetEscherEx() ),
408 mnObjType( nObjType
),
410 nGrbit( 0x6011 ), // AutoLine, AutoFill, Printable, Locked
412 bFirstOnSheet( !rObjMgr
.HasObj() ),
413 mbOwnEscher( bOwnEscher
)
415 //! first object continues the first MSODRAWING record
417 pMsodrawing
= rObjMgr
.GetMsodrawingPerSheet();
419 pMsodrawing
= new XclExpMsoDrawing( mrEscherEx
);
424 if ( !bFirstOnSheet
)
426 pClientTextbox
.reset();
430 void XclObj::ImplWriteAnchor( const SdrObject
* pSdrObj
, const tools::Rectangle
* pChildAnchor
)
434 mrEscherEx
.AddChildAnchor( *pChildAnchor
);
438 std::unique_ptr
< XclExpDffAnchorBase
> xDffAnchor( mrEscherEx
.CreateDffAnchor( *pSdrObj
) );
439 xDffAnchor
->WriteDffData( mrEscherEx
);
443 void XclObj::SetEscherShapeType( sal_uInt16 nType
)
445 //ToDo: what about the other defined or... types?
448 case ESCHER_ShpInst_Line
:
449 mnObjType
= EXC_OBJTYPE_LINE
;
451 case ESCHER_ShpInst_Rectangle
:
452 case ESCHER_ShpInst_RoundRectangle
:
453 mnObjType
= EXC_OBJTYPE_RECTANGLE
;
455 case ESCHER_ShpInst_Ellipse
:
456 mnObjType
= EXC_OBJTYPE_OVAL
;
458 case ESCHER_ShpInst_Arc
:
459 mnObjType
= EXC_OBJTYPE_ARC
;
461 case ESCHER_ShpInst_TextBox
:
462 mnObjType
= EXC_OBJTYPE_TEXT
;
464 case ESCHER_ShpInst_PictureFrame
:
465 mnObjType
= EXC_OBJTYPE_PICTURE
;
468 mnObjType
= EXC_OBJTYPE_DRAWING
;
472 void XclObj::SetText( const XclExpRoot
& rRoot
, const SdrTextObj
& rObj
)
474 OSL_ENSURE( !pClientTextbox
, "XclObj::SetText: already set" );
475 if ( !pClientTextbox
)
477 mrEscherEx
.UpdateDffFragmentEnd();
478 pClientTextbox
.reset( new XclExpMsoDrawing( mrEscherEx
) );
479 mrEscherEx
.AddAtom( 0, ESCHER_ClientTextbox
); // TXO record
480 mrEscherEx
.UpdateDffFragmentEnd();
481 pTxo
.reset( new XclTxo( rRoot
, rObj
) );
485 void XclObj::WriteBody( XclExpStream
& rStrm
)
487 OSL_ENSURE( mnObjType
!= EXC_OBJTYPE_UNKNOWN
, "XclObj::WriteBody - unknown type" );
489 // create a substream to be able to create subrecords
490 SvMemoryStream aMemStrm
;
491 std::optional
< XclExpStream
> pXclStrm( std::in_place
, aMemStrm
, rStrm
.GetRoot() );
493 // write the ftCmo subrecord
494 pXclStrm
->StartRecord( EXC_ID_OBJCMO
, 18 );
495 *pXclStrm
<< mnObjType
<< nObjId
<< nGrbit
;
496 pXclStrm
->WriteZeroBytes( 12 );
497 pXclStrm
->EndRecord();
499 // write other subrecords
500 WriteSubRecs( *pXclStrm
);
502 // write the ftEnd subrecord
503 pXclStrm
->StartRecord( EXC_ID_OBJEND
, 0 );
504 pXclStrm
->EndRecord();
506 // copy the data to the OBJ record
509 rStrm
.CopyFromStream( aMemStrm
);
512 void XclObj::Save( XclExpStream
& rStrm
)
514 // MSODRAWING record (msofbtSpContainer)
515 if ( !bFirstOnSheet
)
516 pMsodrawing
->Save( rStrm
);
519 XclExpRecord::Save( rStrm
);
521 // second MSODRAWING record and TXO and CONTINUE records
522 SaveTextRecs( rStrm
);
525 void XclObj::WriteSubRecs( XclExpStream
& rStrm
)
527 if( mnObjType
!= EXC_OBJTYPE_NOTE
)
533 rStrm
<< EXC_ID_OBJNTS
<< sal_uInt16(0x0016);
535 rtl_createUuid( aGUID
, nullptr, false );
537 rStrm
.SetSliceSize( 16 );
538 for( int i
= 0; i
< 16; i
++ )
540 rStrm
.SetSliceSize( 0 );
542 rStrm
<< sal_uInt16(0);
544 rStrm
.WriteZeroBytes( 4 );
547 void XclObj::SaveTextRecs( XclExpStream
& rStrm
)
549 // MSODRAWING record (msofbtClientTextbox)
550 if ( pClientTextbox
)
551 pClientTextbox
->Save( rStrm
);
552 // TXO and CONTINUE records
557 // --- class XclObjComment ------------------------------------------
559 // tdf#118662 static helper to allow single function access as friend in SdrCaptionObj
560 void setSuppressGetBitmapFromXclObjComment(SdrCaptionObj
* pSdrCaptionObj
, bool bValue
)
562 if(nullptr != pSdrCaptionObj
)
564 pSdrCaptionObj
->setSuppressGetBitmap(bValue
);
568 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
) :
569 XclObj( rObjMgr
, EXC_OBJTYPE_NOTE
, true )
570 , maScPos( rAddress
)
571 , mpCaption( pCaption
)
572 , mbVisible( bVisible
)
576 // tdf#118662 due to no longer cloning the SdrCaptionObj an old 'hack' using the
577 // fact that no Graphics gets created when a SdrObject is not inserted in a SdrPage
578 // does not work anymore. In SvxShape::GetBitmap that info was used, and here the
579 // SdrCaptionObj was cloned for the only reason to have one not added to a SdrPage.
580 // To emulate old behaviour, use a boolean flag at the SdrCaptionObj.
581 setSuppressGetBitmapFromXclObjComment(mpCaption
, true);
583 ProcessEscherObj( rObjMgr
.GetRoot(), rRect
, pCaption
, bVisible
);
585 pTxo
.reset(new XclTxo( rObjMgr
.GetRoot(), rEditObj
, pCaption
));
588 static void lcl_FillProps( EscherPropertyContainer
& rPropOpt
, SdrObject
* pCaption
, bool bVisible
)
592 Reference
< XShape
> aXShape
= GetXShapeForSdrObject( pCaption
);
593 Reference
< XPropertySet
> aXPropSet( aXShape
, UNO_QUERY
);
596 rPropOpt
.CreateFillProperties( aXPropSet
, true);
598 rPropOpt
.AddOpt( ESCHER_Prop_lTxid
, 0 ); // undocumented
599 rPropOpt
.AddOpt( 0x0158, 0x00000000 ); // undocumented
601 sal_uInt32 nValue
= 0;
602 if( !rPropOpt
.GetOpt( ESCHER_Prop_FitTextToShape
, nValue
) )
603 rPropOpt
.AddOpt( ESCHER_Prop_FitTextToShape
, 0x00080008 ); // bool field
605 // Maybe the colour is the same as the 'ToolTip' System colour, but the tooltip
606 // colour shouldn't have influence on the fill colour of the exported shape
607 if( !rPropOpt
.GetOpt( ESCHER_Prop_fillColor
, nValue
) )
608 rPropOpt
.AddOpt( ESCHER_Prop_fillColor
, 0x08000050 );
609 if( !rPropOpt
.GetOpt( ESCHER_Prop_fillBackColor
, nValue
) )
610 rPropOpt
.AddOpt( ESCHER_Prop_fillBackColor
, 0x08000050 );
611 if( !rPropOpt
.GetOpt( ESCHER_Prop_fNoFillHitTest
, nValue
) )
612 rPropOpt
.AddOpt( ESCHER_Prop_fNoFillHitTest
, 0x00110010 ); // bool field
613 if( !rPropOpt
.GetOpt( ESCHER_Prop_shadowColor
, nValue
) )
614 rPropOpt
.AddOpt( ESCHER_Prop_shadowColor
, 0x00000000 );
615 if( !rPropOpt
.GetOpt( ESCHER_Prop_fshadowObscured
, nValue
) ) // bool field
616 rPropOpt
.AddOpt( ESCHER_Prop_fshadowObscured
, 0x00030003 ); // bool field
620 sal_uInt32 nFlags
= 0x000A0000;
621 ::set_flag( nFlags
, sal_uInt32(2), !bVisible
);
622 rPropOpt
.AddOpt( ESCHER_Prop_fPrint
, nFlags
); // bool field
625 void XclObjComment::ProcessEscherObj( const XclExpRoot
& rRoot
, const tools::Rectangle
& rRect
, SdrObject
* pCaption
, const bool bVisible
)
627 EscherPropertyContainer aPropOpt
;
629 lcl_FillProps( aPropOpt
, pCaption
, bVisible
);
631 nGrbit
= 0; // all off: AutoLine, AutoFill, Printable, Locked
632 mrEscherEx
.OpenContainer( ESCHER_SpContainer
);
633 mrEscherEx
.AddShape( ESCHER_ShpInst_TextBox
, ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
);
634 aPropOpt
.Commit( mrEscherEx
.GetStream() );
636 XclExpDffNoteAnchor( rRoot
, rRect
).WriteDffData( mrEscherEx
);
638 mrEscherEx
.AddAtom( 0, ESCHER_ClientData
); // OBJ record
639 mrEscherEx
.UpdateDffFragmentEnd();
641 //! Be sure to construct the MSODRAWING ClientTextbox record _after_ the
642 //! base OBJ's MSODRAWING record Escher data is completed.
643 pClientTextbox
.reset( new XclExpMsoDrawing( mrEscherEx
) );
644 mrEscherEx
.AddAtom( 0, ESCHER_ClientTextbox
); // TXO record
645 mrEscherEx
.UpdateDffFragmentEnd();
646 mrEscherEx
.CloseContainer(); // ESCHER_SpContainer
649 XclObjComment::~XclObjComment()
651 // tdf#118662 reset flag
652 setSuppressGetBitmapFromXclObjComment(mpCaption
, false);
655 void XclObjComment::Save( XclExpStream
& rStrm
)
657 // content of this record
658 XclObj::Save( rStrm
);
663 class VmlCommentExporter
: public VMLExport
666 SdrCaptionObj
* mpCaption
;
668 tools::Rectangle maFrom
;
669 tools::Rectangle maTo
;
672 VmlCommentExporter ( const sax_fastparser::FSHelperPtr
& p
, const ScAddress
& aScPos
, SdrCaptionObj
* pCaption
, bool bVisible
, const tools::Rectangle
&aFrom
, const tools::Rectangle
&aTo
);
674 virtual void Commit( EscherPropertyContainer
& rProps
, const tools::Rectangle
& rRect
) override
;
675 using VMLExport::StartShape
;
676 virtual sal_Int32
StartShape() override
;
677 using VMLExport::EndShape
;
678 virtual void EndShape( sal_Int32 nShapeElement
) override
;
683 VmlCommentExporter::VmlCommentExporter( const sax_fastparser::FSHelperPtr
& p
, const ScAddress
& aScPos
, SdrCaptionObj
* pCaption
,
684 bool bVisible
, const tools::Rectangle
&aFrom
, const tools::Rectangle
&aTo
)
687 , mpCaption( pCaption
)
688 , mbVisible( bVisible
)
694 void VmlCommentExporter::Commit( EscherPropertyContainer
& rProps
, const tools::Rectangle
& rRect
)
696 lcl_FillProps( rProps
, mpCaption
, mbVisible
);
697 rProps
.AddOpt( ESCHER_Prop_fHidden
, sal_uInt32(mbVisible
) ); // bool field
699 // shadow property value for comment ( set in lcl_FillProps [*] ) has been
700 // overwritten by new value ( 0x20000 ) in the generic part of the export
701 // ( see EscherPropertyContainer::CreateShadowProperties )
702 // Safer option here is to just force the needed value here for oox vml
703 // export alone ( and avoid potential problems with binary export )
704 // #TODO investigate value of ESCHER_Prop_fshadowObscured generally
705 // in binary export ( if indeed this value is good for binary export )
706 // we can change the heuristics and/or initialisation path and get
707 // rid of line below.
708 // [*] lcl_FillProps seems to be called twice when exporting to xlsx
709 // once from XclObjComment::ProcessEscherObj #TODO look into that also
710 rProps
.AddOpt( ESCHER_Prop_fshadowObscured
, 0x00030003 ); // force value for comments
712 VMLExport::Commit( rProps
, rRect
);
715 sal_Int32
VmlCommentExporter::StartShape()
717 AddShapeAttribute( XML_type
, "#_x0000_t202" );
719 sal_Int32 nId
= VMLExport::StartShape();
724 static const char* lcl_GetHorizAlignFromItemSetChar(const SfxItemSet
& rItemSet
)
726 switch (rItemSet
.Get(EE_PARA_JUST
).GetAdjust())
728 case SvxAdjust::Center
:
730 case SvxAdjust::Right
:
732 case SvxAdjust::Block
:
739 static const char* lcl_GetVertAlignFromItemSetChar( const SfxItemSet
& rItemSet
)
741 switch( rItemSet
.Get( SDRATTR_TEXT_VERTADJUST
).GetValue() )
743 case SDRTEXTVERTADJUST_CENTER
:
745 case SDRTEXTVERTADJUST_BOTTOM
:
747 case SDRTEXTVERTADJUST_BLOCK
:
749 case SDRTEXTVERTADJUST_TOP
:
755 void VmlCommentExporter::EndShape( sal_Int32 nShapeElement
)
758 sax_fastparser::FSHelperPtr pVmlDrawing
= GetFS();
759 snprintf( pAnchor
, 100, "%" SAL_PRIdINT64
", %" SAL_PRIdINT64
", %" SAL_PRIdINT64
", %" SAL_PRIdINT64
", %" SAL_PRIdINT64
", %" SAL_PRIdINT64
", %" SAL_PRIdINT64
", %" SAL_PRIdINT64
,
760 sal_Int64(maFrom
.Left()), sal_Int64(maFrom
.Top()), sal_Int64(maFrom
.Right()), sal_Int64(maFrom
.Bottom()),
761 sal_Int64(maTo
.Left()), sal_Int64(maTo
.Top()), sal_Int64(maTo
.Right()), sal_Int64(maTo
.Bottom()) );
763 // Getting comment text alignments
764 const char* pVertAlign
= lcl_GetVertAlignFromItemSetChar(mpCaption
->GetMergedItemSet());
765 const char* pHorizAlign
= lcl_GetHorizAlignFromItemSetChar(mpCaption
->GetMergedItemSet());
767 pVmlDrawing
->startElement(FSNS(XML_x
, XML_ClientData
), XML_ObjectType
, "Note");
768 pVmlDrawing
->singleElement(FSNS(XML_x
, XML_MoveWithCells
));
769 pVmlDrawing
->singleElement(FSNS(XML_x
, XML_SizeWithCells
));
770 XclXmlUtils::WriteElement( pVmlDrawing
, FSNS( XML_x
, XML_Anchor
), pAnchor
);
771 XclXmlUtils::WriteElement( pVmlDrawing
, FSNS( XML_x
, XML_AutoFill
), "False" );
772 XclXmlUtils::WriteElement( pVmlDrawing
, FSNS( XML_x
, XML_TextVAlign
), pVertAlign
);
773 XclXmlUtils::WriteElement( pVmlDrawing
, FSNS( XML_x
, XML_TextHAlign
), pHorizAlign
);
774 XclXmlUtils::WriteElement( pVmlDrawing
, FSNS( XML_x
, XML_Row
), maScPos
.Row() );
775 XclXmlUtils::WriteElement( pVmlDrawing
, FSNS(XML_x
, XML_Column
), sal_Int32(maScPos
.Col()));
777 pVmlDrawing
->singleElement(FSNS(XML_x
, XML_Visible
));
778 pVmlDrawing
->endElement( FSNS( XML_x
, XML_ClientData
) );
780 VMLExport::EndShape( nShapeElement
);
783 void XclObjComment::SaveXml( XclExpXmlStream
& rStrm
)
785 VmlCommentExporter
aCommentExporter( rStrm
.GetCurrentStream(), maScPos
, mpCaption
, mbVisible
, maFrom
, maTo
);
786 aCommentExporter
.AddSdrObject( *mpCaption
);
789 // --- class XclObjDropDown ------------------------------------------
791 XclObjDropDown::XclObjDropDown( XclExpObjectManager
& rObjMgr
, const ScAddress
& rPos
, bool bFilt
) :
792 XclObj( rObjMgr
, EXC_OBJTYPE_DROPDOWN
, true ),
796 SetPrintable( false );
798 SetAutoLine( false );
799 nGrbit
|= 0x0100; // undocumented
800 mrEscherEx
.OpenContainer( ESCHER_SpContainer
);
801 mrEscherEx
.AddShape( ESCHER_ShpInst_HostControl
, ShapeFlag::HaveAnchor
| ShapeFlag::HaveShapeProperty
);
802 EscherPropertyContainer aPropOpt
;
803 aPropOpt
.AddOpt( ESCHER_Prop_LockAgainstGrouping
, 0x01040104 ); // bool field
804 aPropOpt
.AddOpt( ESCHER_Prop_FitTextToShape
, 0x00080008 ); // bool field
805 aPropOpt
.AddOpt( ESCHER_Prop_fNoFillHitTest
, 0x00010000 ); // bool field
806 aPropOpt
.AddOpt( ESCHER_Prop_fNoLineDrawDash
, 0x00080000 ); // bool field
807 aPropOpt
.AddOpt( ESCHER_Prop_fPrint
, 0x000A0000 ); // bool field
808 aPropOpt
.Commit( mrEscherEx
.GetStream() );
810 XclExpDffDropDownAnchor( rObjMgr
.GetRoot(), rPos
).WriteDffData( mrEscherEx
);
812 mrEscherEx
.AddAtom( 0, ESCHER_ClientData
); // OBJ record
813 mrEscherEx
.UpdateDffFragmentEnd();
814 mrEscherEx
.CloseContainer(); // ESCHER_SpContainer
816 // old size + ftSbs + ftLbsData
817 AddRecSize( 24 + 20 );
820 XclObjDropDown::~XclObjDropDown()
824 void XclObjDropDown::WriteSubRecs( XclExpStream
& rStrm
)
826 // ftSbs subrecord - Scroll bars (dummy)
827 rStrm
.StartRecord( EXC_ID_OBJSBS
, 20 );
828 rStrm
.WriteZeroBytes( 20 );
831 // ftLbsData subrecord - Listbox data
832 sal_uInt16 nDropDownFlags
= 0;
833 ::insert_value( nDropDownFlags
, EXC_OBJ_DROPDOWN_SIMPLE
, 0, 2 );
834 ::set_flag( nDropDownFlags
, EXC_OBJ_DROPDOWN_FILTERED
, bIsFiltered
);
835 rStrm
.StartRecord( EXC_ID_OBJLBSDATA
, 16 );
836 rStrm
<< sal_uInt32(0) << sal_uInt16(0) << sal_uInt16(0x0301) << sal_uInt16(0)
837 << nDropDownFlags
<< sal_uInt16( 20 ) << sal_uInt16( 130 );
841 // --- class XclTxo --------------------------------------------------
843 static sal_uInt8
lcl_GetHorAlignFromItemSet( const SfxItemSet
& rItemSet
)
845 sal_uInt8 nHorAlign
= EXC_OBJ_HOR_LEFT
;
847 switch( rItemSet
.Get( EE_PARA_JUST
).GetAdjust() )
849 case SvxAdjust::Left
: nHorAlign
= EXC_OBJ_HOR_LEFT
; break;
850 case SvxAdjust::Center
: nHorAlign
= EXC_OBJ_HOR_CENTER
; break;
851 case SvxAdjust::Right
: nHorAlign
= EXC_OBJ_HOR_RIGHT
; break;
852 case SvxAdjust::Block
: nHorAlign
= EXC_OBJ_HOR_JUSTIFY
; break;
858 static sal_uInt8
lcl_GetVerAlignFromItemSet( const SfxItemSet
& rItemSet
)
860 sal_uInt8 nVerAlign
= EXC_OBJ_VER_TOP
;
862 switch( rItemSet
.Get( SDRATTR_TEXT_VERTADJUST
).GetValue() )
864 case SDRTEXTVERTADJUST_TOP
: nVerAlign
= EXC_OBJ_VER_TOP
; break;
865 case SDRTEXTVERTADJUST_CENTER
: nVerAlign
= EXC_OBJ_VER_CENTER
; break;
866 case SDRTEXTVERTADJUST_BOTTOM
: nVerAlign
= EXC_OBJ_VER_BOTTOM
; break;
867 case SDRTEXTVERTADJUST_BLOCK
: nVerAlign
= EXC_OBJ_VER_JUSTIFY
; break;
873 XclTxo::XclTxo( const OUString
& rString
, sal_uInt16 nFontIx
) :
874 mpString( std::make_shared
<XclExpString
>( rString
) ),
875 mnRotation( EXC_OBJ_ORIENT_NONE
),
876 mnHorAlign( EXC_OBJ_HOR_LEFT
),
877 mnVerAlign( EXC_OBJ_VER_TOP
)
879 if( mpString
->Len() )
881 // If there is text, Excel *needs* the 2nd CONTINUE record with at least two format runs
882 mpString
->AppendFormat( 0, nFontIx
);
883 mpString
->AppendFormat( mpString
->Len(), EXC_FONT_APP
);
887 XclTxo::XclTxo( const XclExpRoot
& rRoot
, const SdrTextObj
& rTextObj
) :
888 mpString( XclExpStringHelper::CreateString( rRoot
, rTextObj
) ),
889 mnRotation( EXC_OBJ_ORIENT_NONE
),
890 mnHorAlign( EXC_OBJ_HOR_LEFT
),
891 mnVerAlign( EXC_OBJ_VER_TOP
)
893 // additional alignment and orientation items
894 const SfxItemSet
& rItemSet
= rTextObj
.GetMergedItemSet();
896 // horizontal alignment
897 SetHorAlign( lcl_GetHorAlignFromItemSet( rItemSet
) );
899 // vertical alignment
900 SetVerAlign( lcl_GetVerAlignFromItemSet( rItemSet
) );
903 Degree100 nAngle
= rTextObj
.GetRotateAngle();
904 if( (4500_deg100
< nAngle
) && (nAngle
< 13500_deg100
) )
905 mnRotation
= EXC_OBJ_ORIENT_90CCW
;
906 else if( (22500_deg100
< nAngle
) && (nAngle
< 31500_deg100
) )
907 mnRotation
= EXC_OBJ_ORIENT_90CW
;
909 mnRotation
= EXC_OBJ_ORIENT_NONE
;
912 XclTxo::XclTxo( const XclExpRoot
& rRoot
, const EditTextObject
& rEditObj
, SdrObject
* pCaption
) :
913 mpString( XclExpStringHelper::CreateString( rRoot
, rEditObj
) ),
914 mnRotation( EXC_OBJ_ORIENT_NONE
),
915 mnHorAlign( EXC_OBJ_HOR_LEFT
),
916 mnVerAlign( EXC_OBJ_VER_TOP
)
921 // Excel has one alignment per NoteObject while Calc supports
922 // one alignment per paragraph - use the first paragraph
923 // alignment (if set) as our overall alignment.
924 OUString
aParaText( rEditObj
.GetText( 0 ) );
925 if( !aParaText
.isEmpty() )
927 const SfxItemSet
& aSet( rEditObj
.GetParaAttribs( 0));
928 if( const SvxAdjustItem
* pItem
= aSet
.GetItemIfSet( EE_PARA_JUST
) )
930 SvxAdjust eEEAlign
= pItem
->GetAdjust();
931 pCaption
->SetMergedItem( SvxAdjustItem( eEEAlign
, EE_PARA_JUST
) );
934 const SfxItemSet
& rItemSet
= pCaption
->GetMergedItemSet();
936 // horizontal alignment
937 SetHorAlign( lcl_GetHorAlignFromItemSet( rItemSet
) );
939 // vertical alignment
940 SetVerAlign( lcl_GetVerAlignFromItemSet( rItemSet
) );
942 // orientation alignment
943 const SvxWritingModeItem
& rItem
= rItemSet
.Get( SDRATTR_TEXTDIRECTION
);
944 if( rItem
.GetValue() == css::text::WritingMode_TB_RL
)
945 mnRotation
= EXC_OBJ_ORIENT_90CW
;
948 void XclTxo::SaveCont( XclExpStream
& rStrm
)
950 OSL_ENSURE( mpString
, "XclTxo::SaveCont - missing string" );
952 // #i96858# do not save existing string formatting if text is empty
953 sal_uInt16 nRunLen
= mpString
->IsEmpty() ? 0 : (8 * mpString
->GetFormatsCount());
955 sal_uInt16 nFlags
= 0;
956 ::insert_value( nFlags
, mnHorAlign
, 1, 3 );
957 ::insert_value( nFlags
, mnVerAlign
, 4, 3 );
959 rStrm
<< nFlags
<< mnRotation
;
960 rStrm
.WriteZeroBytes( 6 );
961 rStrm
<< mpString
->Len() << nRunLen
<< sal_uInt32( 0 );
964 void XclTxo::Save( XclExpStream
& rStrm
)
966 // Write the TXO part
967 ExcRecord::Save( rStrm
);
969 // CONTINUE records are only written if there is some text
970 if( mpString
->IsEmpty() )
973 // CONTINUE for character array
974 rStrm
.StartRecord( EXC_ID_CONT
, mpString
->GetBufferSize() + 1 );
975 rStrm
<< static_cast< sal_uInt8
>( mpString
->GetFlagField() & EXC_STRF_16BIT
); // only Unicode flag
976 mpString
->WriteBuffer( rStrm
);
979 // CONTINUE for formatting runs
980 rStrm
.StartRecord( EXC_ID_CONT
, 8 * mpString
->GetFormatsCount() );
981 const XclFormatRunVec
& rFormats
= mpString
->GetFormats();
982 for( const auto& rFormat
: rFormats
)
983 rStrm
<< rFormat
.mnChar
<< rFormat
.mnFontIdx
<< sal_uInt32( 0 );
987 sal_uInt16
XclTxo::GetNum() const
992 std::size_t XclTxo::GetLen() const
997 // --- class XclObjOle -------------------------------------------
999 XclObjOle::XclObjOle( XclExpObjectManager
& rObjMgr
, const SdrObject
& rObj
) :
1000 XclObj( rObjMgr
, EXC_OBJTYPE_PICTURE
),
1002 pRootStorage( rObjMgr
.GetRoot().GetRootStorage().get() )
1006 XclObjOle::~XclObjOle()
1010 void XclObjOle::WriteSubRecs( XclExpStream
& rStrm
)
1012 // write only as embedded, not linked
1013 OUString
aStorageName( "MBD" );
1014 char aBuf
[ sizeof(sal_uInt32
) * 2 + 1 ];
1015 // FIXME Eeek! Is this just a way to get a unique id?
1016 sal_uInt32 nPictureId
= sal_uInt32(reinterpret_cast<sal_uIntPtr
>(this) >> 2);
1017 o3tl::sprintf( aBuf
, "%08X", static_cast< unsigned int >( nPictureId
) );
1018 aStorageName
+= OUString::createFromAscii(aBuf
);
1019 tools::SvRef
<SotStorage
> xOleStg
= pRootStorage
->OpenSotStorage( aStorageName
);
1023 uno::Reference
< embed::XEmbeddedObject
> xObj( static_cast<const SdrOle2Obj
&>(rOleObj
).GetObjRef() );
1027 // set version to "old" version, because it must be
1028 // saved in MS notation.
1030 const SvtFilterOptions
& rFltOpts
= SvtFilterOptions::Get();
1031 if( rFltOpts
.IsMath2MathType() )
1032 nFl
|= OLE_STARMATH_2_MATHTYPE
;
1034 if( rFltOpts
.IsWriter2WinWord() )
1035 nFl
|= OLE_STARWRITER_2_WINWORD
;
1037 if( rFltOpts
.IsCalc2Excel() )
1038 nFl
|= OLE_STARCALC_2_EXCEL
;
1040 if( rFltOpts
.IsImpress2PowerPoint() )
1041 nFl
|= OLE_STARIMPRESS_2_POWERPOINT
;
1043 SvxMSExportOLEObjects
aOLEExpFilt( nFl
);
1044 aOLEExpFilt
.ExportOLEObject( xObj
, *xOleStg
);
1046 // OBJCF subrecord, undocumented as usual
1047 rStrm
.StartRecord( EXC_ID_OBJCF
, 2 );
1048 rStrm
<< sal_uInt16(0x0002);
1051 // OBJFLAGS subrecord, undocumented as usual
1052 rStrm
.StartRecord( EXC_ID_OBJFLAGS
, 2 );
1053 sal_uInt16 nFlags
= EXC_OBJ_PIC_MANUALSIZE
;
1054 ::set_flag( nFlags
, EXC_OBJ_PIC_SYMBOL
, static_cast<const SdrOle2Obj
&>(rOleObj
).GetAspect() == embed::Aspects::MSOLE_ICON
);
1058 // OBJPICTFMLA subrecord, undocumented as usual
1059 XclExpString
aName( xOleStg
->GetUserName() );
1060 sal_uInt16 nPadLen
= static_cast<sal_uInt16
>(aName
.GetSize() & 0x01);
1061 sal_uInt16 nFmlaLen
= static_cast< sal_uInt16
>( 12 + aName
.GetSize() + nPadLen
);
1062 sal_uInt16 nSubRecLen
= nFmlaLen
+ 6;
1064 rStrm
.StartRecord( EXC_ID_OBJPICTFMLA
, nSubRecLen
);
1066 << sal_uInt16( 5 ) << sal_uInt32( 0 ) << sal_uInt8( 2 )
1067 << sal_uInt32( 0 ) << sal_uInt8( 3 )
1070 rStrm
<< sal_uInt8( 0 ); // pad byte
1071 rStrm
<< nPictureId
;
1075 void XclObjOle::Save( XclExpStream
& rStrm
)
1077 // content of this record
1078 XclObj::Save( rStrm
);
1081 // --- class XclObjAny -------------------------------------------
1083 XclObjAny::XclObjAny( XclExpObjectManager
& rObjMgr
, const Reference
< XShape
>& rShape
, ScDocument
* pDoc
)
1084 : XclObj( rObjMgr
, EXC_OBJTYPE_UNKNOWN
)
1090 XclObjAny::~XclObjAny()
1094 void XclObjAny::WriteSubRecs( XclExpStream
& rStrm
)
1096 if( mnObjType
== EXC_OBJTYPE_GROUP
)
1098 rStrm
<< EXC_ID_OBJGMO
<< sal_uInt16(2) << sal_uInt16(0);
1101 void XclObjAny::Save( XclExpStream
& rStrm
)
1103 if( mnObjType
== EXC_OBJTYPE_GROUP
)
1107 // content of this record
1108 XclObj::Save( rStrm
);
1111 // --- class ExcBof8_Base --------------------------------------------
1113 ExcBof8_Base::ExcBof8_Base()
1120 void XclObjAny::WriteFromTo( XclExpXmlStream
& rStrm
, const Reference
< XShape
>& rShape
, SCTAB nTab
)
1122 sax_fastparser::FSHelperPtr pDrawing
= rStrm
.GetCurrentStream();
1124 awt::Point aTopLeft
= rShape
->getPosition();
1125 awt::Size aSize
= rShape
->getSize();
1127 // There are a few cases where we must adjust these values
1128 // Do not adjust objects, which have rotation incorporated into their points
1129 // but report a rotation angle nevertheless.
1130 SdrObject
* pObj
= SdrObject::getSdrObjectFromXShape(rShape
);
1131 if (pObj
&& pObj
->GetObjIdentifier() != SdrObjKind::Line
&& pObj
->GetObjIdentifier() != SdrObjKind::PolyLine
1132 && pObj
->GetObjIdentifier() != SdrObjKind::PathLine
&& pObj
->GetObjIdentifier() != SdrObjKind::FreehandLine
1133 && pObj
->GetObjIdentifier() != SdrObjKind::PathPolyLine
)
1135 Degree100 nRotation
= NormAngle36000(pObj
->GetRotateAngle());
1138 sal_Int16 nHalfWidth
= aSize
.Width
/ 2;
1139 sal_Int16 nHalfHeight
= aSize
.Height
/ 2;
1141 // Center of bounding box of the rotated shape
1142 const auto aSnapRectCenter(pObj
->GetSnapRect().Center());
1143 aTopLeft
.X
= aSnapRectCenter
.X() - nHalfWidth
;
1144 aTopLeft
.Y
= aSnapRectCenter
.Y() - nHalfHeight
;
1146 // MSO changes the anchor positions at these angles and that does an extra 90 degrees
1147 // rotation on our shapes, so we output it in such position that MSO
1148 // can draw this shape correctly.
1149 if ((nRotation
> 4500_deg100
&& nRotation
<= 13500_deg100
) || (nRotation
> 22500_deg100
&& nRotation
<= 31500_deg100
))
1151 aTopLeft
.X
= aTopLeft
.X
- nHalfHeight
+ nHalfWidth
;
1152 aTopLeft
.Y
= aTopLeft
.Y
- nHalfWidth
+ nHalfHeight
;
1154 std::swap(aSize
.Width
, aSize
.Height
);
1159 tools::Rectangle
aLocation( aTopLeft
.X
, aTopLeft
.Y
, aTopLeft
.X
+ aSize
.Width
, aTopLeft
.Y
+ aSize
.Height
);
1160 ScRange aRange
= rStrm
.GetRoot().GetDoc().GetRange( nTab
, aLocation
);
1161 tools::Rectangle aRangeRect
= rStrm
.GetRoot().GetDoc().GetMMRect( aRange
.aStart
.Col(), aRange
.aStart
.Row(),
1162 aRange
.aEnd
.Col()-1, aRange
.aEnd
.Row()-1,
1165 pDrawing
->startElement(FSNS(XML_xdr
, XML_from
));
1166 XclXmlUtils::WriteElement( pDrawing
, FSNS( XML_xdr
, XML_col
), static_cast<sal_Int32
>(aRange
.aStart
.Col()) );
1167 XclXmlUtils::WriteElement( pDrawing
, FSNS( XML_xdr
, XML_colOff
),
1168 oox::drawingml::convertHmmToEmu( aLocation
.Left() - aRangeRect
.Left() ) );
1169 XclXmlUtils::WriteElement( pDrawing
, FSNS( XML_xdr
, XML_row
), static_cast<sal_Int32
>(aRange
.aStart
.Row()) );
1170 XclXmlUtils::WriteElement( pDrawing
, FSNS( XML_xdr
, XML_rowOff
),
1171 oox::drawingml::convertHmmToEmu( aLocation
.Top() - aRangeRect
.Top() ) );
1172 pDrawing
->endElement( FSNS( XML_xdr
, XML_from
) );
1174 pDrawing
->startElement(FSNS(XML_xdr
, XML_to
));
1175 XclXmlUtils::WriteElement( pDrawing
, FSNS( XML_xdr
, XML_col
), static_cast<sal_Int32
>(aRange
.aEnd
.Col()) );
1176 XclXmlUtils::WriteElement( pDrawing
, FSNS( XML_xdr
, XML_colOff
),
1177 oox::drawingml::convertHmmToEmu( aLocation
.Right() - aRangeRect
.Right() ) );
1178 XclXmlUtils::WriteElement( pDrawing
, FSNS( XML_xdr
, XML_row
), static_cast<sal_Int32
>(aRange
.aEnd
.Row()) );
1179 XclXmlUtils::WriteElement( pDrawing
, FSNS( XML_xdr
, XML_rowOff
),
1180 oox::drawingml::convertHmmToEmu( aLocation
.Bottom() - aRangeRect
.Bottom() ) );
1181 pDrawing
->endElement( FSNS( XML_xdr
, XML_to
) );
1184 void XclObjAny::WriteFromTo( XclExpXmlStream
& rStrm
, const XclObjAny
& rObj
)
1186 WriteFromTo( rStrm
, rObj
.GetShape(), rObj
.GetTab() );
1190 GetEditAs( const XclObjAny
& rObj
)
1192 if( const SdrObject
* pShape
= EscherEx::GetSdrObject( rObj
.GetShape() ) )
1194 switch( ScDrawLayer::GetAnchorType( *pShape
) )
1198 case SCA_CELL_RESIZE
:
1210 ScRefFlags
parseRange(const OUString
& rString
, ScRange
& rRange
, const ScDocument
& rDoc
)
1212 // start with the address convention set in the document
1213 formula::FormulaGrammar::AddressConvention eConv
= rDoc
.GetAddressConvention();
1214 ScRefFlags nResult
= rRange
.Parse(rString
, rDoc
, eConv
);
1215 if ( nResult
& ScRefFlags::VALID
)
1218 // try the default calc address convention
1219 nResult
= rRange
.Parse(rString
, rDoc
);
1220 if ( nResult
& ScRefFlags::VALID
)
1224 nResult
= rRange
.Parse(rString
, rDoc
, formula::FormulaGrammar::CONV_XL_A1
);
1225 if ( nResult
& ScRefFlags::VALID
)
1229 return rRange
.Parse(rString
, rDoc
, formula::FormulaGrammar::CONV_XL_R1C1
);
1232 ScRefFlags
parseAddress(const OUString
& rString
, ScAddress
& rAddress
, const ScDocument
& rDoc
)
1234 // start with the address convention set in the document
1235 formula::FormulaGrammar::AddressConvention eConv
= rDoc
.GetAddressConvention();
1236 ScRefFlags nResult
= rAddress
.Parse(rString
, rDoc
, eConv
);
1237 if ( nResult
& ScRefFlags::VALID
)
1240 // try the default calc address convention
1241 nResult
= rAddress
.Parse(rString
, rDoc
);
1242 if ( nResult
& ScRefFlags::VALID
)
1246 nResult
= rAddress
.Parse(rString
, rDoc
, formula::FormulaGrammar::CONV_XL_A1
);
1247 if ( nResult
& ScRefFlags::VALID
)
1251 return rAddress
.Parse(rString
, rDoc
, formula::FormulaGrammar::CONV_XL_R1C1
);
1254 void transformURL(const OUString
& rOldURL
, OUString
& rNewURL
, const ScDocument
& rDoc
)
1256 if (rOldURL
.startsWith("#"))
1258 // URL has to be decoded for escaped characters (%20)
1259 OUString aURL
= INetURLObject::decode( rOldURL
,
1260 INetURLObject::DecodeMechanism::WithCharset
);
1261 OUString aAddressString
= aURL
.copy(1);
1264 ScRefFlags nResult
= parseRange(aAddressString
, aRange
, rDoc
);
1265 if ( nResult
& ScRefFlags::VALID
)
1267 OUString aString
= aRange
.Format(rDoc
, nResult
, formula::FormulaGrammar::CONV_XL_OOX
);
1268 rNewURL
= "#" + aString
;
1274 nResult
= parseAddress(aAddressString
, aAddress
, rDoc
);
1275 if( nResult
& ScRefFlags::VALID
)
1277 OUString aString
= aAddress
.Format(nResult
, &rDoc
, formula::FormulaGrammar::CONV_XL_OOX
);
1278 rNewURL
= "#" + aString
;
1289 ScURLTransformer::ScURLTransformer(ScDocument
& rDoc
)
1294 OUString
ScURLTransformer::getTransformedString(const OUString
& rURL
) const
1297 transformURL(rURL
, aNewURL
, mrDoc
);
1301 bool ScURLTransformer::isExternalURL(const OUString
& rURL
) const
1303 return !rURL
.startsWith("#");
1306 void XclObjAny::SaveXml( XclExpXmlStream
& rStrm
)
1308 // Do not output any of the detective shapes and validation circles.
1309 SdrObject
* pObject
= SdrObject::getSdrObjectFromXShape(mxShape
);
1312 ScDocument
& rDoc
= rStrm
.GetRoot().GetDoc();
1313 ScDetectiveFunc
aDetFunc(rDoc
, mnScTab
);
1314 ScAddress aPosition
;
1315 ScRange aSourceRange
;
1317 ScDetectiveObjType eObjType
1318 = aDetFunc
.GetDetectiveObjectType(pObject
, mnScTab
, aPosition
, aSourceRange
, bRedLine
);
1320 if (eObjType
!= SC_DETOBJ_NONE
)
1324 sax_fastparser::FSHelperPtr pDrawing
= rStrm
.GetCurrentStream();
1326 ShapeExport
aDML(XML_xdr
, pDrawing
, nullptr, &rStrm
, drawingml::DOCUMENT_XLSX
);
1327 auto pURLTransformer
= std::make_shared
<ScURLTransformer
>(*mpDoc
);
1328 aDML
.SetURLTranslator(pURLTransformer
);
1330 pDrawing
->startElement( FSNS( XML_xdr
, XML_twoCellAnchor
), // OOXTODO: oneCellAnchor, absoluteAnchor
1331 XML_editAs
, GetEditAs( *this ) );
1332 Reference
< XPropertySet
> xPropSet( mxShape
, UNO_QUERY
);
1335 WriteFromTo( rStrm
, *this );
1336 aDML
.WriteShape( mxShape
);
1339 pDrawing
->singleElement( FSNS( XML_xdr
, XML_clientData
)
1340 // OOXTODO: XML_fLocksWithSheet
1341 // OOXTODO: XML_fPrintsWithSheet
1343 pDrawing
->endElement( FSNS( XML_xdr
, XML_twoCellAnchor
) );
1346 void ExcBof8_Base::SaveCont( XclExpStream
& rStrm
)
1348 rStrm
.DisableEncryption();
1349 rStrm
<< nVers
<< nDocType
<< nRupBuild
<< nRupYear
1350 << sal_uInt32(0)/*nFileHistory*/
1351 << sal_uInt32(0x06) /*nLowestBiffVer = Biff8*/;
1354 sal_uInt16
ExcBof8_Base::GetNum() const
1359 std::size_t ExcBof8_Base::GetLen() const
1364 // --- class ExcBof8 -------------------------------------------------
1371 // --- class ExcBofW8 ------------------------------------------------
1373 ExcBofW8::ExcBofW8()
1378 // --- class ExcBundlesheet8 -----------------------------------------
1380 ExcBundlesheet8::ExcBundlesheet8( const RootData
& rRootData
, SCTAB _nTab
) :
1381 ExcBundlesheetBase( rRootData
, static_cast<sal_uInt16
>(_nTab
) ),
1382 sUnicodeName( rRootData
.pER
->GetTabInfo().GetScTabName( _nTab
) )
1386 ExcBundlesheet8::ExcBundlesheet8( OUString aString
) :
1387 sUnicodeName(std::move( aString
))
1391 void ExcBundlesheet8::SaveCont( XclExpStream
& rStrm
)
1393 m_nOwnPos
= rStrm
.GetSvStreamPos();
1394 // write dummy position, real position comes later
1395 rStrm
.DisableEncryption();
1396 rStrm
<< sal_uInt32(0);
1397 rStrm
.EnableEncryption();
1398 rStrm
<< nGrbit
<< GetName();
1401 std::size_t ExcBundlesheet8::GetLen() const
1402 { // Text max 255 chars
1403 return 8 + GetName().GetBufferSize();
1406 void ExcBundlesheet8::SaveXml( XclExpXmlStream
& rStrm
)
1409 rStrm
.CreateOutputStream(
1410 XclXmlUtils::GetStreamName( "xl/", "worksheets/sheet", nTab
+1),
1411 XclXmlUtils::GetStreamName( nullptr, "worksheets/sheet", nTab
+1),
1412 rStrm
.GetCurrentStream()->getOutputStream(),
1413 "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
1414 oox::getRelationship(Relationship::WORKSHEET
),
1417 rStrm
.GetCurrentStream()->singleElement( XML_sheet
,
1418 XML_name
, sUnicodeName
.toUtf8(),
1419 XML_sheetId
, OString::number( nTab
+1 ),
1420 XML_state
, nGrbit
== 0x0000 ? "visible" : "hidden",
1421 FSNS( XML_r
, XML_id
), sId
.toUtf8() );
1424 // --- class XclObproj -----------------------------------------------
1426 sal_uInt16
XclObproj::GetNum() const
1431 std::size_t XclObproj::GetLen() const
1436 // ---- class XclCodename --------------------------------------------
1438 XclCodename::XclCodename( const OUString
& r
) : aName( r
)
1442 void XclCodename::SaveCont( XclExpStream
& rStrm
)
1447 sal_uInt16
XclCodename::GetNum() const
1452 std::size_t XclCodename::GetLen() const
1454 return aName
.GetSize();
1457 // ---- Scenarios ----------------------------------------------------
1459 ExcEScenarioCell::ExcEScenarioCell( sal_uInt16 nC
, sal_uInt16 nR
, const OUString
& rTxt
) :
1462 sText( rTxt
, XclStrFlags::NONE
, 255 )
1466 void ExcEScenarioCell::WriteAddress( XclExpStream
& rStrm
) const
1468 rStrm
<< nRow
<< nCol
;
1471 void ExcEScenarioCell::WriteText( XclExpStream
& rStrm
) const
1476 void ExcEScenarioCell::SaveXml( XclExpXmlStream
& rStrm
) const
1478 rStrm
.GetCurrentStream()->singleElement( XML_inputCells
,
1479 // OOXTODO: XML_deleted,
1480 // OOXTODO: XML_numFmtId,
1481 XML_r
, XclXmlUtils::ToOString( rStrm
.GetRoot().GetDoc(), ScAddress( nCol
, nRow
, 0 ) ),
1482 // OOXTODO: XML_undone,
1483 XML_val
, XclXmlUtils::ToOString( sText
) );
1486 ExcEScenario::ExcEScenario( const XclExpRoot
& rRoot
, SCTAB nTab
)
1492 ScScenarioFlags nFlags
;
1494 ScDocument
& rDoc
= rRoot
.GetDoc();
1495 rDoc
.GetName(nTab
, aTmp
);
1497 sName
.Assign( sTmpName
, XclStrFlags::EightBitLength
);
1498 nRecLen
= 8 + sName
.GetBufferSize();
1500 rDoc
.GetScenarioData( nTab
, aTmp
, aDummyCol
, nFlags
);
1502 sComment
.Assign( sTmpComm
, XclStrFlags::NONE
, 255 );
1503 if( sComment
.Len() )
1504 nRecLen
+= sComment
.GetSize();
1505 bProtected
= (nFlags
& ScScenarioFlags::Protected
) != ScScenarioFlags::NONE
;
1507 sUserName
.Assign( rRoot
.GetUserName(), XclStrFlags::NONE
, 255 );
1508 nRecLen
+= sUserName
.GetSize();
1510 const ScRangeList
* pRList
= rDoc
.GetScenarioRanges( nTab
);
1514 bool bContLoop
= true;
1520 for( size_t nRange
= 0; (nRange
< pRList
->size()) && bContLoop
; nRange
++ )
1522 const ScRange
& rRange
= (*pRList
)[nRange
];
1523 for( nRow
= rRange
.aStart
.Row(); (nRow
<= rRange
.aEnd
.Row()) && bContLoop
; nRow
++ )
1524 for( nCol
= rRange
.aStart
.Col(); (nCol
<= rRange
.aEnd
.Col()) && bContLoop
; nCol
++ )
1526 if( rDoc
.HasValueData( nCol
, nRow
, nTab
) )
1528 fVal
= rDoc
.GetValue( nCol
, nRow
, nTab
);
1529 sText
= ::rtl::math::doubleToUString( fVal
,
1530 rtl_math_StringFormat_Automatic
,
1531 rtl_math_DecimalPlaces_Max
,
1532 ScGlobal::getLocaleData().getNumDecimalSep()[0],
1536 sText
= rDoc
.GetString(nCol
, nRow
, nTab
);
1537 bContLoop
= Append( static_cast<sal_uInt16
>(nCol
),
1538 static_cast<sal_uInt16
>(nRow
), sText
);
1543 bool ExcEScenario::Append( sal_uInt16 nCol
, sal_uInt16 nRow
, const OUString
& rTxt
)
1545 if( aCells
.size() == EXC_SCEN_MAXCELL
)
1548 ExcEScenarioCell
aCell(nCol
, nRow
, rTxt
);
1549 aCells
.push_back(aCell
);
1550 nRecLen
+= 6 + aCell
.GetStringBytes(); // 4 bytes address, 2 bytes ifmt
1554 void ExcEScenario::SaveCont( XclExpStream
& rStrm
)
1556 sal_uInt16 count
= aCells
.size();
1558 rStrm
<< count
// number of cells
1559 << sal_uInt8(bProtected
) // fProtection
1560 << sal_uInt8(0) // fHidden
1561 << static_cast<sal_uInt8
>(sName
.Len()) // length of scen name
1562 << static_cast<sal_uInt8
>(sComment
.Len()) // length of comment
1563 << static_cast<sal_uInt8
>(sUserName
.Len()); // length of user name
1564 sName
.WriteFlagField( rStrm
);
1565 sName
.WriteBuffer( rStrm
);
1569 if( sComment
.Len() )
1572 for( const auto& rCell
: aCells
)
1573 rCell
.WriteAddress( rStrm
); // pos of cell
1574 for( const auto& rCell
: aCells
)
1575 rCell
.WriteText( rStrm
); // string content
1576 rStrm
.SetSliceSize( 2 );
1577 rStrm
.WriteZeroBytes( 2 * count
); // date format
1580 sal_uInt16
ExcEScenario::GetNum() const
1585 std::size_t ExcEScenario::GetLen() const
1590 void ExcEScenario::SaveXml( XclExpXmlStream
& rStrm
)
1592 sax_fastparser::FSHelperPtr
& rWorkbook
= rStrm
.GetCurrentStream();
1593 rWorkbook
->startElement( XML_scenario
,
1594 XML_name
, XclXmlUtils::ToOString( sName
).getStr(),
1595 XML_locked
, ToPsz( bProtected
),
1596 // OOXTODO: XML_hidden,
1597 XML_count
, OString::number( aCells
.size() ).getStr(),
1598 XML_user
, XESTRING_TO_PSZ( sUserName
),
1599 XML_comment
, XESTRING_TO_PSZ( sComment
) );
1601 for( const auto& rCell
: aCells
)
1602 rCell
.SaveXml( rStrm
);
1604 rWorkbook
->endElement( XML_scenario
);
1607 ExcEScenarioManager::ExcEScenarioManager( const XclExpRoot
& rRoot
, SCTAB nTab
) :
1610 ScDocument
& rDoc
= rRoot
.GetDoc();
1611 if( rDoc
.IsScenario( nTab
) )
1614 SCTAB nFirstTab
= nTab
+ 1;
1615 SCTAB nNewTab
= nFirstTab
;
1617 while( rDoc
.IsScenario( nNewTab
) )
1619 aScenes
.emplace_back( rRoot
, nNewTab
);
1621 if( rDoc
.IsActiveScenario( nNewTab
) )
1622 nActive
= static_cast<sal_uInt16
>(nNewTab
- nFirstTab
);
1627 ExcEScenarioManager::~ExcEScenarioManager()
1631 void ExcEScenarioManager::SaveCont( XclExpStream
& rStrm
)
1633 rStrm
<< static_cast<sal_uInt16
>(aScenes
.size()) // number of scenarios
1634 << nActive
// active scen
1635 << nActive
// last displayed
1636 << sal_uInt16(0); // reference areas
1639 void ExcEScenarioManager::Save( XclExpStream
& rStrm
)
1641 if( !aScenes
.empty() )
1642 ExcRecord::Save( rStrm
);
1644 for( ExcEScenario
& rScenario
: aScenes
)
1645 rScenario
.Save( rStrm
);
1648 void ExcEScenarioManager::SaveXml( XclExpXmlStream
& rStrm
)
1650 if( aScenes
.empty() )
1653 sax_fastparser::FSHelperPtr
& rWorkbook
= rStrm
.GetCurrentStream();
1654 rWorkbook
->startElement( XML_scenarios
,
1655 XML_current
, OString::number( nActive
),
1656 XML_show
, OString::number( nActive
)
1657 // OOXTODO: XML_sqref
1660 for( ExcEScenario
& rScenario
: aScenes
)
1661 rScenario
.SaveXml( rStrm
);
1663 rWorkbook
->endElement( XML_scenarios
);
1666 sal_uInt16
ExcEScenarioManager::GetNum() const
1671 std::size_t ExcEScenarioManager::GetLen() const
1678 struct XclExpTabProtectOption
1680 ScTableProtection::Option eOption
;
1686 XclExpSheetProtectOptions::XclExpSheetProtectOptions( const XclExpRoot
& rRoot
, SCTAB nTab
) :
1687 XclExpRecord( 0x0867, 23 )
1689 static const XclExpTabProtectOption aTable
[] =
1691 { ScTableProtection::OBJECTS
, 0x0001 },
1692 { ScTableProtection::SCENARIOS
, 0x0002 },
1693 { ScTableProtection::FORMAT_CELLS
, 0x0004 },
1694 { ScTableProtection::FORMAT_COLUMNS
, 0x0008 },
1695 { ScTableProtection::FORMAT_ROWS
, 0x0010 },
1696 { ScTableProtection::INSERT_COLUMNS
, 0x0020 },
1697 { ScTableProtection::INSERT_ROWS
, 0x0040 },
1698 { ScTableProtection::INSERT_HYPERLINKS
, 0x0080 },
1700 { ScTableProtection::DELETE_COLUMNS
, 0x0100 },
1701 { ScTableProtection::DELETE_ROWS
, 0x0200 },
1702 { ScTableProtection::SELECT_LOCKED_CELLS
, 0x0400 },
1703 { ScTableProtection::SORT
, 0x0800 },
1704 { ScTableProtection::AUTOFILTER
, 0x1000 },
1705 { ScTableProtection::PIVOT_TABLES
, 0x2000 },
1706 { ScTableProtection::SELECT_UNLOCKED_CELLS
, 0x4000 },
1708 { ScTableProtection::NONE
, 0x0000 }
1712 const ScTableProtection
* pProtect
= rRoot
.GetDoc().GetTabProtection(nTab
);
1716 for (int i
= 0; aTable
[i
].nMask
!= 0x0000; ++i
)
1718 if ( pProtect
->isOptionEnabled(aTable
[i
].eOption
) )
1719 mnOptions
|= aTable
[i
].nMask
;
1723 void XclExpSheetProtectOptions::WriteBody( XclExpStream
& rStrm
)
1725 sal_uInt16 nBytes
= 0x0867;
1728 for (int i
= 0; i
< 9; ++i
)
1729 rStrm
<< static_cast<unsigned char>(0);
1736 rStrm
<< nBytes
<< nBytes
;
1743 XclExpSheetEnhancedProtection::XclExpSheetEnhancedProtection( const XclExpRoot
& rRoot
,
1744 ScEnhancedProtection aProt
) :
1745 XclExpRecord( 0x0868 ),
1747 maEnhancedProtection(std::move( aProt
))
1751 void XclExpSheetEnhancedProtection::WriteBody( XclExpStream
& rStrm
)
1753 sal_uInt16
const nRecordType
= 0x0868;
1754 rStrm
<< nRecordType
; // frtHeader rt
1755 rStrm
.WriteZeroBytesToRecord(10); // frtHeader unused
1756 rStrm
<< EXC_ISFPROTECTION
; // isf
1757 rStrm
.WriteZeroBytesToRecord(5); // reserved1 (1 bytes) and reserved2 (4 bytes)
1760 if (maEnhancedProtection
.maRangeList
.is())
1761 mrRoot
.GetAddressConverter().ConvertRangeList( aRefs
, *maEnhancedProtection
.maRangeList
, false);
1762 sal_uInt16 nCref
= ulimit_cast
<sal_uInt16
>(aRefs
.size());
1763 rStrm
<< nCref
; // cref
1764 rStrm
.WriteZeroBytesToRecord(6); // cbFeatData if EXC_ISFFEC2 (4 bytes) and reserved3 (2 bytes)
1765 aRefs
.Write( rStrm
, true, nCref
); // refs
1767 // FeatProtection structure
1768 rStrm
<< maEnhancedProtection
.mnAreserved
; // 1 bit A and 31 bits reserved
1769 rStrm
<< maEnhancedProtection
.mnPasswordVerifier
; // wPassword
1770 rStrm
<< XclExpString( maEnhancedProtection
.maTitle
); // stTitle
1771 bool bSDContainer
= ((maEnhancedProtection
.mnAreserved
& 0x00000001) == 0x00000001);
1772 sal_uInt32 nCbSD
= maEnhancedProtection
.maSecurityDescriptor
.size();
1773 SAL_WARN_IF( bSDContainer
&& nCbSD
< 20, "sc.filter",
1774 "XclExpSheetEnhancedProtection A flag indicates container but cbSD < 20");
1775 SAL_WARN_IF( !bSDContainer
&& nCbSD
> 0, "sc.filter",
1776 "XclExpSheetEnhancedProtection A flag indicates no container but cbSD > 0");
1780 rStrm
.Write( &maEnhancedProtection
.maSecurityDescriptor
.front(), nCbSD
);
1784 void XclCalccount::SaveCont( XclExpStream
& rStrm
)
1789 XclCalccount::XclCalccount( const ScDocument
& rDoc
)
1791 nCount
= rDoc
.GetDocOptions().GetIterCount();
1794 sal_uInt16
XclCalccount::GetNum() const
1799 std::size_t XclCalccount::GetLen() const
1804 void XclCalccount::SaveXml( XclExpXmlStream
& rStrm
)
1806 rStrm
.WriteAttributes(XML_iterateCount
, OUString::number(nCount
));
1809 void XclIteration::SaveCont( XclExpStream
& rStrm
)
1814 XclIteration::XclIteration( const ScDocument
& rDoc
)
1816 nIter
= rDoc
.GetDocOptions().IsIter()? 1 : 0;
1819 sal_uInt16
XclIteration::GetNum() const
1824 std::size_t XclIteration::GetLen() const
1829 void XclIteration::SaveXml( XclExpXmlStream
& rStrm
)
1831 rStrm
.WriteAttributes(XML_iterate
, ToPsz(nIter
== 1));
1834 void XclDelta::SaveCont( XclExpStream
& rStrm
)
1839 XclDelta::XclDelta( const ScDocument
& rDoc
)
1841 fDelta
= rDoc
.GetDocOptions().GetIterEps();
1844 sal_uInt16
XclDelta::GetNum() const
1849 std::size_t XclDelta::GetLen() const
1854 void XclDelta::SaveXml( XclExpXmlStream
& rStrm
)
1856 rStrm
.WriteAttributes(XML_iterateDelta
, OUString::number(fDelta
));
1859 XclExpFileEncryption::XclExpFileEncryption( const XclExpRoot
& rRoot
) :
1860 XclExpRecord(0x002F, 54),
1865 XclExpFileEncryption::~XclExpFileEncryption()
1869 void XclExpFileEncryption::WriteBody( XclExpStream
& rStrm
)
1871 // 0x0000 - neither standard nor strong encryption
1872 // 0x0001 - standard or strong encryption
1873 rStrm
<< static_cast<sal_uInt16
>(0x0001);
1875 // 0x0000 - non standard encryption
1876 // 0x0001 - standard encryption
1877 sal_uInt16 nStdEnc
= 0x0001;
1878 rStrm
<< nStdEnc
<< nStdEnc
;
1880 sal_uInt8 pnDocId
[16];
1881 sal_uInt8 pnSalt
[16];
1882 sal_uInt8 pnSaltHash
[16];
1883 XclExpEncrypterRef xEnc
= std::make_shared
<XclExpBiff8Encrypter
>(mrRoot
);
1884 xEnc
->GetDocId(pnDocId
);
1885 xEnc
->GetSalt(pnSalt
);
1886 xEnc
->GetSaltDigest(pnSaltHash
);
1888 rStrm
.Write(pnDocId
, 16);
1889 rStrm
.Write(pnSalt
, 16);
1890 rStrm
.Write(pnSaltHash
, 16);
1892 rStrm
.SetEncrypter(xEnc
);
1895 XclExpInterfaceHdr::XclExpInterfaceHdr( sal_uInt16 nCodePage
) :
1896 XclExpUInt16Record( EXC_ID_INTERFACEHDR
, nCodePage
)
1900 void XclExpInterfaceHdr::WriteBody( XclExpStream
& rStrm
)
1902 rStrm
.DisableEncryption();
1903 rStrm
<< GetValue();
1906 XclExpInterfaceEnd::XclExpInterfaceEnd() :
1907 XclExpRecord(0x00E2, 0) {}
1909 XclExpInterfaceEnd::~XclExpInterfaceEnd() {}
1911 void XclExpInterfaceEnd::WriteBody( XclExpStream
& rStrm
)
1913 // Don't forget to re-enable encryption.
1914 rStrm
.EnableEncryption();
1917 XclExpWriteAccess::XclExpWriteAccess() :
1918 XclExpRecord(0x005C, 112)
1922 XclExpWriteAccess::~XclExpWriteAccess()
1926 void XclExpWriteAccess::WriteBody( XclExpStream
& rStrm
)
1928 static const sal_uInt8 aData
[] = {
1929 0x04, 0x00, 0x00, 'C', 'a', 'l', 'c', 0x20,
1930 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1931 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1932 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1933 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1934 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1935 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1936 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1937 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1938 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1939 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1940 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1941 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
1942 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
1944 for (std::size_t i
= 0; i
< sizeof(aData
); ++i
)
1948 XclExpFileSharing::XclExpFileSharing( const XclExpRoot
& rRoot
, sal_uInt16 nPasswordHash
, bool bRecommendReadOnly
) :
1949 XclExpRecord( EXC_ID_FILESHARING
),
1950 mnPasswordHash( nPasswordHash
),
1951 mbRecommendReadOnly( bRecommendReadOnly
)
1953 if( rRoot
.GetBiff() <= EXC_BIFF5
)
1954 maUserName
.AssignByte( rRoot
.GetUserName(), rRoot
.GetTextEncoding(), XclStrFlags::EightBitLength
);
1956 maUserName
.Assign( rRoot
.GetUserName() );
1959 void XclExpFileSharing::Save( XclExpStream
& rStrm
)
1961 if( (mnPasswordHash
!= 0) || mbRecommendReadOnly
)
1962 XclExpRecord::Save( rStrm
);
1965 void XclExpFileSharing::WriteBody( XclExpStream
& rStrm
)
1967 rStrm
<< sal_uInt16( mbRecommendReadOnly
? 1 : 0 ) << mnPasswordHash
<< maUserName
;
1970 XclExpProt4Rev::XclExpProt4Rev() :
1971 XclExpRecord(0x01AF, 2)
1975 XclExpProt4Rev::~XclExpProt4Rev()
1979 void XclExpProt4Rev::WriteBody( XclExpStream
& rStrm
)
1981 rStrm
<< static_cast<sal_uInt16
>(0x0000);
1984 XclExpProt4RevPass::XclExpProt4RevPass() :
1985 XclExpRecord(0x01BC, 2)
1989 XclExpProt4RevPass::~XclExpProt4RevPass()
1993 void XclExpProt4RevPass::WriteBody( XclExpStream
& rStrm
)
1995 rStrm
<< static_cast<sal_uInt16
>(0x0000);
1998 const sal_uInt8 nDataRecalcId
[] = {
1999 0xC1, 0x01, 0x00, 0x00, 0x54, 0x8D, 0x01, 0x00
2002 XclExpRecalcId::XclExpRecalcId() :
2003 XclExpDummyRecord(0x01C1, nDataRecalcId
, sizeof(nDataRecalcId
))
2007 const sal_uInt8 nDataBookExt
[] = {
2008 0x63, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2009 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2013 XclExpBookExt::XclExpBookExt() :
2014 XclExpDummyRecord(0x0863, nDataBookExt
, sizeof(nDataBookExt
))
2018 XclRefmode::XclRefmode( const ScDocument
& rDoc
) :
2019 XclExpBoolRecord( 0x000F, rDoc
.GetAddressConvention() != formula::FormulaGrammar::CONV_XL_R1C1
)
2023 void XclRefmode::SaveXml( XclExpXmlStream
& rStrm
)
2025 rStrm
.WriteAttributes(XML_refMode
, GetBool() ? "A1" : "R1C1");
2028 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */