fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / filter / excel / xeescher.cxx
blob9caee24d6d433a3d725176b4fbceeaaa45618b97
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 "xeescher.hxx"
22 #include <com/sun/star/lang/XServiceInfo.hpp>
23 #include <com/sun/star/frame/XModel.hpp>
24 #include <com/sun/star/form/FormComponentType.hpp>
25 #include <com/sun/star/awt/VisualEffect.hpp>
26 #include <com/sun/star/awt/ScrollBarOrientation.hpp>
27 #include <com/sun/star/drawing/XShape.hpp>
28 #include <com/sun/star/form/binding/XBindableValue.hpp>
29 #include <com/sun/star/form/binding/XValueBinding.hpp>
30 #include <com/sun/star/form/binding/XListEntrySink.hpp>
31 #include <com/sun/star/form/binding/XListEntrySource.hpp>
32 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
33 #include <com/sun/star/chart2/XChartDocument.hpp>
34 #include <com/sun/star/awt/Point.hpp>
35 #include <com/sun/star/awt/Size.hpp>
36 #include <com/sun/star/container/XNamed.hpp>
38 #include <set>
39 #include <rtl/ustrbuf.h>
40 #include <vcl/bmpacc.hxx>
41 #include <svx/svdoole2.hxx>
42 #include <svx/svdocapt.hxx>
43 #include <editeng/outlobj.hxx>
44 #include <editeng/editobj.hxx>
45 #include <unotools/tempfile.hxx>
46 #include <unotools/ucbstreamhelper.hxx>
47 #include <svtools/embedhlp.hxx>
49 #include "editutil.hxx"
50 #include "unonames.hxx"
51 #include "convuno.hxx"
52 #include "postit.hxx"
54 #include "fapihelper.hxx"
55 #include "xechart.hxx"
56 #include "xeformula.hxx"
57 #include "xelink.hxx"
58 #include "xename.hxx"
59 #include "xestyle.hxx"
60 #include "userdat.hxx"
61 #include "drwlayer.hxx"
62 #include <svx/unoapi.hxx>
63 #include <svx/algitem.hxx>
64 #include "scitems.hxx"
65 #include <editeng/justifyitem.hxx>
66 #include <svx/sdtaitm.hxx>
67 #include "attrib.hxx"
68 #include "document.hxx"
69 #include <svx/svdattr.hxx>
70 #include <svx/sdr/properties/properties.hxx>
71 #include "detfunc.hxx"
72 #include <svx/xflclit.hxx>
73 #include <svx/xlnstwit.hxx>
74 #include <svx/xlnstit.hxx>
75 #include <svx/sxmspitm.hxx>
77 #include <oox/token/tokens.hxx>
78 #include <oox/export/drawingml.hxx>
79 #include <oox/export/chartexport.hxx>
80 #include <oox/export/utils.hxx>
81 #include <memory>
83 using namespace com::sun::star;
84 using ::com::sun::star::uno::UNO_QUERY;
85 using ::com::sun::star::uno::Reference;
86 using ::com::sun::star::uno::Sequence;
87 using ::com::sun::star::lang::XServiceInfo;
88 using ::com::sun::star::beans::XPropertySet;
89 using ::com::sun::star::drawing::XShape;
90 using ::com::sun::star::drawing::XShapes;
91 using ::com::sun::star::frame::XModel;
92 using ::com::sun::star::embed::XEmbeddedObject;
93 using ::com::sun::star::awt::XControlModel;
94 using ::com::sun::star::form::binding::XBindableValue;
95 using ::com::sun::star::form::binding::XValueBinding;
96 using ::com::sun::star::form::binding::XListEntrySink;
97 using ::com::sun::star::form::binding::XListEntrySource;
98 using ::com::sun::star::script::ScriptEventDescriptor;
99 using ::com::sun::star::table::CellAddress;
100 using ::com::sun::star::table::CellRangeAddress;
101 using ::com::sun::star::chart2::XChartDocument;
102 using ::com::sun::star::container::XNamed;
103 using ::oox::drawingml::DrawingML;
104 using ::oox::drawingml::ChartExport;
105 using namespace oox;
107 #define HMM2XL(x) ((x)/26.5)+0.5
109 #if 1//def XLSX_OOXML_FUTURE
110 // these function are only used within that context
111 // Static Function Helpers
112 static const char *ToHorizAlign( SdrTextHorzAdjust eAdjust )
114 switch( eAdjust )
116 case SDRTEXTHORZADJUST_CENTER:
117 return "center";
118 case SDRTEXTHORZADJUST_RIGHT:
119 return "right";
120 case SDRTEXTHORZADJUST_BLOCK:
121 return "justify";
122 case SDRTEXTHORZADJUST_LEFT:
123 default:
124 return "left";
128 static const char *ToVertAlign( SdrTextVertAdjust eAdjust )
130 switch( eAdjust )
132 case SDRTEXTVERTADJUST_CENTER:
133 return "center";
134 case SDRTEXTVERTADJUST_BOTTOM:
135 return "bottom";
136 case SDRTEXTVERTADJUST_BLOCK:
137 return "justify";
138 case SDRTEXTVERTADJUST_TOP:
139 default:
140 return "top";
144 static void lcl_WriteAnchorVertex( sax_fastparser::FSHelperPtr rComments, Rectangle &aRect )
146 rComments->startElement( FSNS( XML_xdr, XML_col ), FSEND );
147 rComments->writeEscaped( OUString::number( aRect.Left() ) );
148 rComments->endElement( FSNS( XML_xdr, XML_col ) );
149 rComments->startElement( FSNS( XML_xdr, XML_colOff ), FSEND );
150 rComments->writeEscaped( OUString::number( aRect.Top() ) );
151 rComments->endElement( FSNS( XML_xdr, XML_colOff ) );
152 rComments->startElement( FSNS( XML_xdr, XML_row ), FSEND );
153 rComments->writeEscaped( OUString::number( aRect.Right() ) );
154 rComments->endElement( FSNS( XML_xdr, XML_row ) );
155 rComments->startElement( FSNS( XML_xdr, XML_rowOff ), FSEND );
156 rComments->writeEscaped( OUString::number( aRect.Bottom() ) );
157 rComments->endElement( FSNS( XML_xdr, XML_rowOff ) );
159 #endif
161 static void lcl_GetFromTo( const XclExpRoot& rRoot, const Rectangle &aRect, sal_Int32 nTab, Rectangle &aFrom, Rectangle &aTo )
163 bool bTo = false;
164 sal_Int32 nCol = 0, nRow = 0;
165 sal_Int32 nColOff = 0, nRowOff= 0;
167 while(true)
169 Rectangle r = rRoot.GetDocPtr()->GetMMRect( nCol,nRow,nCol,nRow,nTab );
170 if( !bTo )
172 if( r.Left() <= aRect.Left() )
174 nCol++;
175 nColOff = aRect.Left() - r.Left();
177 if( r.Top() <= aRect.Top() )
179 nRow++;
180 nRowOff = aRect.Top() - r.Top();
182 if( r.Left() > aRect.Left() && r.Top() > aRect.Top() )
184 aFrom = Rectangle( nCol-1, static_cast<long>(HMM2XL( nColOff )),
185 nRow-1, static_cast<long>(HMM2XL( nRowOff )) );
186 bTo=true;
189 if( bTo )
191 if( r.Right() < aRect.Right() )
192 nCol++;
193 if( r.Bottom() < aRect.Bottom() )
194 nRow++;
195 if( r.Right() >= aRect.Right() && r.Bottom() >= aRect.Bottom() )
197 aTo = Rectangle( nCol, static_cast<long>(HMM2XL( aRect.Right() - r.Left() )),
198 nRow, static_cast<long>(HMM2XL( aRect.Bottom() - r.Top() )));
199 break;
203 return;
206 // Escher client anchor =======================================================
208 XclExpDffAnchorBase::XclExpDffAnchorBase( const XclExpRoot& rRoot, sal_uInt16 nFlags ) :
209 XclExpRoot( rRoot ),
210 mnFlags( nFlags )
214 void XclExpDffAnchorBase::SetFlags( const SdrObject& rSdrObj )
216 ImplSetFlags( rSdrObj );
219 void XclExpDffAnchorBase::SetSdrObject( const SdrObject& rSdrObj )
221 ImplSetFlags( rSdrObj );
222 ImplCalcAnchorRect( rSdrObj.GetCurrentBoundRect(), MAP_100TH_MM );
225 void XclExpDffAnchorBase::WriteDffData( EscherEx& rEscherEx ) const
227 rEscherEx.AddAtom( 18, ESCHER_ClientAnchor );
228 rEscherEx.GetStream().WriteUInt16( mnFlags );
229 WriteXclObjAnchor( rEscherEx.GetStream(), maAnchor );
232 void XclExpDffAnchorBase::WriteData( EscherEx& rEscherEx, const Rectangle& rRect )
234 // the passed rectangle is in twips
235 ImplCalcAnchorRect( rRect, MAP_TWIP );
236 WriteDffData( rEscherEx );
239 void XclExpDffAnchorBase::ImplSetFlags( const SdrObject& )
241 OSL_FAIL( "XclExpDffAnchorBase::ImplSetFlags - not implemented" );
244 void XclExpDffAnchorBase::ImplCalcAnchorRect( const Rectangle&, MapUnit )
246 OSL_FAIL( "XclExpDffAnchorBase::ImplCalcAnchorRect - not implemented" );
249 XclExpDffSheetAnchor::XclExpDffSheetAnchor( const XclExpRoot& rRoot ) :
250 XclExpDffAnchorBase( rRoot ),
251 mnScTab( rRoot.GetCurrScTab() )
255 void XclExpDffSheetAnchor::ImplSetFlags( const SdrObject& rSdrObj )
257 // set flags for cell/page anchoring
258 if ( ScDrawLayer::GetAnchorType( rSdrObj ) == SCA_CELL )
259 mnFlags = 0;
260 else
261 mnFlags = EXC_ESC_ANCHOR_LOCKED;
264 void XclExpDffSheetAnchor::ImplCalcAnchorRect( const Rectangle& rRect, MapUnit eMapUnit )
266 maAnchor.SetRect( GetRoot(), mnScTab, rRect, eMapUnit );
269 XclExpDffEmbeddedAnchor::XclExpDffEmbeddedAnchor( const XclExpRoot& rRoot,
270 const Size& rPageSize, sal_Int32 nScaleX, sal_Int32 nScaleY ) :
271 XclExpDffAnchorBase( rRoot ),
272 maPageSize( rPageSize ),
273 mnScaleX( nScaleX ),
274 mnScaleY( nScaleY )
278 void XclExpDffEmbeddedAnchor::ImplSetFlags( const SdrObject& /*rSdrObj*/ )
280 // TODO (unsupported feature): fixed size
283 void XclExpDffEmbeddedAnchor::ImplCalcAnchorRect( const Rectangle& rRect, MapUnit eMapUnit )
285 maAnchor.SetRect( maPageSize, mnScaleX, mnScaleY, rRect, eMapUnit, true );
288 XclExpDffNoteAnchor::XclExpDffNoteAnchor( const XclExpRoot& rRoot, const Rectangle& rRect ) :
289 XclExpDffAnchorBase( rRoot, EXC_ESC_ANCHOR_SIZELOCKED )
291 maAnchor.SetRect( rRoot, rRoot.GetCurrScTab(), rRect, MAP_100TH_MM );
294 XclExpDffDropDownAnchor::XclExpDffDropDownAnchor( const XclExpRoot& rRoot, const ScAddress& rScPos ) :
295 XclExpDffAnchorBase( rRoot, EXC_ESC_ANCHOR_POSLOCKED )
297 GetAddressConverter().ConvertAddress( maAnchor.maFirst, rScPos, true );
298 maAnchor.maLast.mnCol = maAnchor.maFirst.mnCol + 1;
299 maAnchor.maLast.mnRow = maAnchor.maFirst.mnRow + 1;
300 maAnchor.mnLX = maAnchor.mnTY = maAnchor.mnRX = maAnchor.mnBY = 0;
303 // MSODRAWING* records ========================================================
305 XclExpMsoDrawingBase::XclExpMsoDrawingBase( XclEscherEx& rEscherEx, sal_uInt16 nRecId ) :
306 XclExpRecord( nRecId ),
307 mrEscherEx( rEscherEx ),
308 mnFragmentKey( rEscherEx.InitNextDffFragment() )
312 void XclExpMsoDrawingBase::WriteBody( XclExpStream& rStrm )
314 OSL_ENSURE( mrEscherEx.GetStreamPos() == mrEscherEx.GetDffFragmentPos( mnFragmentKey ),
315 "XclExpMsoDrawingBase::WriteBody - DFF stream position mismatch" );
316 rStrm.CopyFromStream( mrEscherEx.GetStream(), mrEscherEx.GetDffFragmentSize( mnFragmentKey ) );
319 XclExpMsoDrawingGroup::XclExpMsoDrawingGroup( XclEscherEx& rEscherEx ) :
320 XclExpMsoDrawingBase( rEscherEx, EXC_ID_MSODRAWINGGROUP )
322 SvStream& rDffStrm = mrEscherEx.GetStream();
324 // write the DGGCONTAINER with some default settings
325 mrEscherEx.OpenContainer( ESCHER_DggContainer );
327 // TODO: stuff the OPT atom with our own document defaults?
328 static const sal_uInt8 spnDffOpt[] = {
329 0xBF, 0x00, 0x08, 0x00, 0x08, 0x00, 0x81, 0x01,
330 0x09, 0x00, 0x00, 0x08, 0xC0, 0x01, 0x40, 0x00,
331 0x00, 0x08
333 mrEscherEx.AddAtom( sizeof( spnDffOpt ), ESCHER_OPT, 3, 3 );
334 rDffStrm.Write( spnDffOpt, sizeof( spnDffOpt ) );
336 // SPLITMENUCOLORS contains colors in toolbar
337 static const sal_uInt8 spnDffSplitMenuColors[] = {
338 0x0D, 0x00, 0x00, 0x08, 0x0C, 0x00, 0x00, 0x08,
339 0x17, 0x00, 0x00, 0x08, 0xF7, 0x00, 0x00, 0x10
341 mrEscherEx.AddAtom( sizeof( spnDffSplitMenuColors ), ESCHER_SplitMenuColors, 0, 4 );
342 rDffStrm.Write( spnDffSplitMenuColors, sizeof( spnDffSplitMenuColors ) );
344 // close the DGGCONTAINER
345 mrEscherEx.CloseContainer();
346 mrEscherEx.UpdateDffFragmentEnd();
349 XclExpMsoDrawing::XclExpMsoDrawing( XclEscherEx& rEscherEx ) :
350 XclExpMsoDrawingBase( rEscherEx, EXC_ID_MSODRAWING )
354 XclExpImgData::XclExpImgData( const Graphic& rGraphic, sal_uInt16 nRecId ) :
355 maGraphic( rGraphic ),
356 mnRecId( nRecId )
360 void XclExpImgData::Save( XclExpStream& rStrm )
362 Bitmap aBmp = maGraphic.GetBitmap();
363 if( aBmp.GetBitCount() != 24 )
364 aBmp.Convert( BMP_CONVERSION_24BIT );
366 if( BitmapReadAccess* pAccess = aBmp.AcquireReadAccess() )
368 sal_Int32 nWidth = ::std::min< sal_Int32 >( pAccess->Width(), 0xFFFF );
369 sal_Int32 nHeight = ::std::min< sal_Int32 >( pAccess->Height(), 0xFFFF );
370 if( (nWidth > 0) && (nHeight > 0) )
372 sal_uInt8 nPadding = static_cast< sal_uInt8 >( nWidth & 0x03 );
373 sal_uInt32 nTmpSize = static_cast< sal_uInt32 >( (nWidth * 3 + nPadding) * nHeight + 12 );
375 rStrm.StartRecord( mnRecId, nTmpSize + 4 );
377 rStrm << EXC_IMGDATA_BMP // BMP format
378 << EXC_IMGDATA_WIN // Windows
379 << nTmpSize // size after _this_ field
380 << sal_uInt32( 12 ) // BITMAPCOREHEADER size
381 << static_cast< sal_uInt16 >( nWidth ) // width
382 << static_cast< sal_uInt16 >( nHeight ) // height
383 << sal_uInt16( 1 ) // planes
384 << sal_uInt16( 24 ); // bits per pixel
386 for( sal_Int32 nY = nHeight - 1; nY >= 0; --nY )
388 for( sal_Int32 nX = 0; nX < nWidth; ++nX )
390 const BitmapColor& rBmpColor = pAccess->GetPixel( nY, nX );
391 rStrm << rBmpColor.GetBlue() << rBmpColor.GetGreen() << rBmpColor.GetRed();
393 rStrm.WriteZeroBytes( nPadding );
396 rStrm.EndRecord();
398 Bitmap::ReleaseAccess( pAccess );
402 void XclExpImgData::SaveXml( XclExpXmlStream& rStrm )
404 sax_fastparser::FSHelperPtr pWorksheet = rStrm.GetCurrentStream();
406 DrawingML aDML( pWorksheet, &rStrm, DrawingML::DOCUMENT_XLSX );
407 OUString rId = aDML.WriteImage( maGraphic );
408 pWorksheet->singleElement( XML_picture,
409 FSNS( XML_r, XML_id ), XclXmlUtils::ToOString( rId ).getStr(),
410 FSEND );
413 XclExpControlHelper::XclExpControlHelper( const XclExpRoot& rRoot ) :
414 XclExpRoot( rRoot ),
415 mnEntryCount( 0 )
419 XclExpControlHelper::~XclExpControlHelper()
423 void XclExpControlHelper::ConvertSheetLinks( Reference< XShape > xShape )
425 mxCellLink.reset();
426 mxSrcRange.reset();
427 mnEntryCount = 0;
429 // get control model
430 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( xShape );
431 if( !xCtrlModel.is() )
432 return;
434 // *** cell link *** ------------------------------------------------------
436 Reference< XBindableValue > xBindable( xCtrlModel, UNO_QUERY );
437 if( xBindable.is() )
439 Reference< XServiceInfo > xServInfo( xBindable->getValueBinding(), UNO_QUERY );
440 if( xServInfo.is() && xServInfo->supportsService( SC_SERVICENAME_VALBIND ) )
442 ScfPropertySet aBindProp( xServInfo );
443 CellAddress aApiAddress;
444 if( aBindProp.GetProperty( aApiAddress, SC_UNONAME_BOUNDCELL ) )
446 ScAddress aCellLink;
447 ScUnoConversion::FillScAddress( aCellLink, aApiAddress );
448 if( GetTabInfo().IsExportTab( aCellLink.Tab() ) )
449 mxCellLink = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CONTROL, aCellLink );
454 // *** source range *** ---------------------------------------------------
456 Reference< XListEntrySink > xEntrySink( xCtrlModel, UNO_QUERY );
457 if( xEntrySink.is() )
459 Reference< XServiceInfo > xServInfo( xEntrySink->getListEntrySource(), UNO_QUERY );
460 if( xServInfo.is() && xServInfo->supportsService( SC_SERVICENAME_LISTSOURCE ) )
462 ScfPropertySet aSinkProp( xServInfo );
463 CellRangeAddress aApiRange;
464 if( aSinkProp.GetProperty( aApiRange, SC_UNONAME_CELLRANGE ) )
466 ScRange aSrcRange;
467 ScUnoConversion::FillScRange( aSrcRange, aApiRange );
468 if( (aSrcRange.aStart.Tab() == aSrcRange.aEnd.Tab()) && GetTabInfo().IsExportTab( aSrcRange.aStart.Tab() ) )
469 mxSrcRange = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CONTROL, aSrcRange );
470 mnEntryCount = static_cast< sal_uInt16 >( aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1 );
476 void XclExpControlHelper::WriteFormula( XclExpStream& rStrm, const XclTokenArray& rTokArr )
478 sal_uInt16 nFmlaSize = rTokArr.GetSize();
479 rStrm << nFmlaSize << sal_uInt32( 0 );
480 rTokArr.WriteArray( rStrm );
481 if( nFmlaSize & 1 ) // pad to 16-bit
482 rStrm << sal_uInt8( 0 );
485 void XclExpControlHelper::WriteFormulaSubRec( XclExpStream& rStrm, sal_uInt16 nSubRecId, const XclTokenArray& rTokArr )
487 rStrm.StartRecord( nSubRecId, (rTokArr.GetSize() + 5) & ~1 );
488 WriteFormula( rStrm, rTokArr );
489 rStrm.EndRecord();
492 //delete for exporting OCX
493 //#if EXC_EXP_OCX_CTRL
495 XclExpOcxControlObj::XclExpOcxControlObj( XclExpObjectManager& rObjMgr, Reference< XShape > xShape,
496 const Rectangle* pChildAnchor, const OUString& rClassName, sal_uInt32 nStrmStart, sal_uInt32 nStrmSize ) :
497 XclObj( rObjMgr, EXC_OBJTYPE_PICTURE, true ),
498 XclExpControlHelper( rObjMgr.GetRoot() ),
499 maClassName( rClassName ),
500 mnStrmStart( nStrmStart ),
501 mnStrmSize( nStrmSize )
503 ScfPropertySet aCtrlProp( XclControlHelper::GetControlModel( xShape ) );
505 // OBJ record flags
506 SetLocked( true );
507 SetPrintable( aCtrlProp.GetBoolProperty( "Printable" ) );
508 SetAutoFill( false );
509 SetAutoLine( false );
511 // fill DFF property set
512 mrEscherEx.OpenContainer( ESCHER_SpContainer );
513 mrEscherEx.AddShape( ESCHER_ShpInst_HostControl, SHAPEFLAG_HAVESPT | SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_OLESHAPE );
514 Rectangle aDummyRect;
515 EscherPropertyContainer aPropOpt( mrEscherEx.GetGraphicProvider(), mrEscherEx.QueryPictureStream(), aDummyRect );
516 aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x00080008 ); // bool field
517 aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x08000040 );
518 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080000 ); // bool field
520 // #i51348# name of the control, may overwrite shape name
521 OUString aCtrlName;
522 if( aCtrlProp.GetProperty( aCtrlName, "Name" ) && !aCtrlName.isEmpty() )
523 aPropOpt.AddOpt( ESCHER_Prop_wzName, aCtrlName );
525 // meta file
526 //TODO - needs check
527 Reference< XPropertySet > xShapePS( xShape, UNO_QUERY );
528 if( xShapePS.is() && aPropOpt.CreateGraphicProperties( xShapePS, OUString( "MetaFile" ), false ) )
530 sal_uInt32 nBlipId;
531 if( aPropOpt.GetOpt( ESCHER_Prop_pib, nBlipId ) )
532 aPropOpt.AddOpt( ESCHER_Prop_pictureId, nBlipId );
535 // write DFF property set to stream
536 aPropOpt.Commit( mrEscherEx.GetStream() );
538 // anchor
539 ImplWriteAnchor( GetRoot(), SdrObject::getSdrObjectFromXShape( xShape ), pChildAnchor );
541 mrEscherEx.AddAtom( 0, ESCHER_ClientData ); // OBJ record
542 mrEscherEx.CloseContainer(); // ESCHER_SpContainer
543 mrEscherEx.UpdateDffFragmentEnd();
545 // spreadsheet links
546 ConvertSheetLinks( xShape );
549 void XclExpOcxControlObj::WriteSubRecs( XclExpStream& rStrm )
551 // OBJCF - clipboard format
552 rStrm.StartRecord( EXC_ID_OBJCF, 2 );
553 rStrm << sal_uInt16( 2 );
554 rStrm.EndRecord();
556 // OBJFLAGS
557 rStrm.StartRecord( EXC_ID_OBJFLAGS, 2 );
558 rStrm << sal_uInt16( 0x0031 );
559 rStrm.EndRecord();
561 // OBJPICTFMLA
562 XclExpString aClass( maClassName );
563 sal_uInt16 nClassNameSize = static_cast< sal_uInt16 >( aClass.GetSize() );
564 sal_uInt16 nClassNamePad = nClassNameSize & 1;
565 sal_uInt16 nFirstPartSize = 12 + nClassNameSize + nClassNamePad;
567 const XclTokenArray* pCellLink = GetCellLinkTokArr();
568 sal_uInt16 nCellLinkSize = pCellLink ? ((pCellLink->GetSize() + 7) & 0xFFFE) : 0;
570 const XclTokenArray* pSrcRange = GetSourceRangeTokArr();
571 sal_uInt16 nSrcRangeSize = pSrcRange ? ((pSrcRange->GetSize() + 7) & 0xFFFE) : 0;
573 sal_uInt16 nPictFmlaSize = nFirstPartSize + nCellLinkSize + nSrcRangeSize + 18;
574 rStrm.StartRecord( EXC_ID_OBJPICTFMLA, nPictFmlaSize );
576 rStrm << sal_uInt16( nFirstPartSize ) // size of first part
577 << sal_uInt16( 5 ) // formula size
578 << sal_uInt32( 0 ) // unknown ID
579 << sal_uInt8( 0x02 ) << sal_uInt32( 0 ) // tTbl token with unknown ID
580 << sal_uInt8( 3 ) // pad to word
581 << aClass; // "Forms.***.1"
582 rStrm.WriteZeroBytes( nClassNamePad ); // pad to word
583 rStrm << mnStrmStart // start in 'Ctls' stream
584 << mnStrmSize // size in 'Ctls' stream
585 << sal_uInt32( 0 ); // class ID size
586 // cell link
587 rStrm << nCellLinkSize;
588 if( pCellLink )
589 WriteFormula( rStrm, *pCellLink );
590 // list source range
591 rStrm << nSrcRangeSize;
592 if( pSrcRange )
593 WriteFormula( rStrm, *pSrcRange );
595 rStrm.EndRecord();
598 //#else
600 XclExpTbxControlObj::XclExpTbxControlObj( XclExpObjectManager& rRoot, Reference< XShape > xShape , const Rectangle* pChildAnchor ) :
601 XclObj( rRoot, EXC_OBJTYPE_UNKNOWN, true ),
602 XclMacroHelper( rRoot ),
603 meEventType( EXC_TBX_EVENT_ACTION ),
604 mnHeight( 0 ),
605 mnState( 0 ),
606 mnLineCount( 0 ),
607 mnSelEntry( 0 ),
608 mnScrollValue( 0 ),
609 mnScrollMin( 0 ),
610 mnScrollMax( 100 ),
611 mnScrollStep( 1 ),
612 mnScrollPage( 10 ),
613 mbFlatButton( false ),
614 mbFlatBorder( false ),
615 mbMultiSel( false ),
616 mbScrollHor( false )
618 namespace FormCompType = ::com::sun::star::form::FormComponentType;
619 namespace AwtVisualEffect = ::com::sun::star::awt::VisualEffect;
620 namespace AwtScrollOrient = ::com::sun::star::awt::ScrollBarOrientation;
622 ScfPropertySet aCtrlProp( XclControlHelper::GetControlModel( xShape ) );
623 if( !xShape.is() || !aCtrlProp.Is() )
624 return;
626 mnHeight = xShape->getSize().Height;
627 if( mnHeight <= 0 )
628 return;
630 // control type
631 sal_Int16 nClassId = 0;
632 if( aCtrlProp.GetProperty( nClassId, "ClassId" ) )
634 switch( nClassId )
636 case FormCompType::COMMANDBUTTON: mnObjType = EXC_OBJTYPE_BUTTON; meEventType = EXC_TBX_EVENT_ACTION; break;
637 case FormCompType::RADIOBUTTON: mnObjType = EXC_OBJTYPE_OPTIONBUTTON; meEventType = EXC_TBX_EVENT_ACTION; break;
638 case FormCompType::CHECKBOX: mnObjType = EXC_OBJTYPE_CHECKBOX; meEventType = EXC_TBX_EVENT_ACTION; break;
639 case FormCompType::LISTBOX: mnObjType = EXC_OBJTYPE_LISTBOX; meEventType = EXC_TBX_EVENT_CHANGE; break;
640 case FormCompType::COMBOBOX: mnObjType = EXC_OBJTYPE_DROPDOWN; meEventType = EXC_TBX_EVENT_CHANGE; break;
641 case FormCompType::GROUPBOX: mnObjType = EXC_OBJTYPE_GROUPBOX; meEventType = EXC_TBX_EVENT_MOUSE; break;
642 case FormCompType::FIXEDTEXT: mnObjType = EXC_OBJTYPE_LABEL; meEventType = EXC_TBX_EVENT_MOUSE; break;
643 case FormCompType::SCROLLBAR: mnObjType = EXC_OBJTYPE_SCROLLBAR; meEventType = EXC_TBX_EVENT_VALUE; break;
644 case FormCompType::SPINBUTTON: mnObjType = EXC_OBJTYPE_SPIN; meEventType = EXC_TBX_EVENT_VALUE; break;
647 if( mnObjType == EXC_OBJTYPE_UNKNOWN )
648 return;
650 // OBJ record flags
651 SetLocked( true );
652 SetPrintable( aCtrlProp.GetBoolProperty( "Printable" ) );
653 SetAutoFill( false );
654 SetAutoLine( false );
656 // fill DFF property set
657 mrEscherEx.OpenContainer( ESCHER_SpContainer );
658 mrEscherEx.AddShape( ESCHER_ShpInst_HostControl, SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_HAVESPT );
659 EscherPropertyContainer aPropOpt;
660 bool bVisible = aCtrlProp.GetBoolProperty( "EnableVisible" );
661 aPropOpt.AddOpt( ESCHER_Prop_fPrint, bVisible ? 0x00080000 : 0x00080002 ); // visible flag
663 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x01000100 ); // bool field
664 aPropOpt.AddOpt( ESCHER_Prop_lTxid, 0 ); // Text ID
665 aPropOpt.AddOpt( ESCHER_Prop_WrapText, 0x00000001 );
666 aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x001A0008 ); // bool field
667 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x00100000 ); // bool field
668 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080000 ); // bool field
670 // #i51348# name of the control, may overwrite shape name
671 OUString aCtrlName;
672 if( aCtrlProp.GetProperty( aCtrlName, "Name" ) && !aCtrlName.isEmpty() )
673 aPropOpt.AddOpt( ESCHER_Prop_wzName, aCtrlName );
675 //Export description as alt text
676 if( SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape( xShape ) )
678 OUString aAltTxt;
679 OUString aDescrText = pSdrObj->GetDescription();
680 if(!aDescrText.isEmpty())
681 aAltTxt = aDescrText.copy( 0, std::min<sal_Int32>(MSPROP_DESCRIPTION_MAX_LEN, aDescrText.getLength()) );
682 aPropOpt.AddOpt( ESCHER_Prop_wzDescription, aAltTxt );
685 // write DFF property set to stream
686 aPropOpt.Commit( mrEscherEx.GetStream() );
688 // anchor
689 ImplWriteAnchor( GetRoot(), SdrObject::getSdrObjectFromXShape( xShape ), pChildAnchor );
691 mrEscherEx.AddAtom( 0, ESCHER_ClientData ); // OBJ record
692 mrEscherEx.UpdateDffFragmentEnd();
694 // control label
695 OUString aString;
696 if( aCtrlProp.GetProperty( aString, "Label" ) )
698 /* Be sure to construct the MSODRAWING record containing the
699 ClientTextbox atom after the base OBJ's MSODRAWING record data is
700 completed. */
701 pClientTextbox = new XclExpMsoDrawing( mrEscherEx );
702 mrEscherEx.AddAtom( 0, ESCHER_ClientTextbox ); // TXO record
703 mrEscherEx.UpdateDffFragmentEnd();
705 sal_uInt16 nXclFont = EXC_FONT_APP;
706 if( !aString.isEmpty() )
708 XclFontData aFontData;
709 GetFontPropSetHelper().ReadFontProperties( aFontData, aCtrlProp, EXC_FONTPROPSET_CONTROL );
710 if( (!aFontData.maName.isEmpty() ) && (aFontData.mnHeight > 0) )
711 nXclFont = GetFontBuffer().Insert( aFontData, EXC_COLOR_CTRLTEXT );
714 pTxo = new XclTxo( aString, nXclFont );
715 pTxo->SetHorAlign( (mnObjType == EXC_OBJTYPE_BUTTON) ? EXC_OBJ_HOR_CENTER : EXC_OBJ_HOR_LEFT );
716 pTxo->SetVerAlign( EXC_OBJ_VER_CENTER );
719 mrEscherEx.CloseContainer(); // ESCHER_SpContainer
721 // other properties
722 aCtrlProp.GetProperty( mnLineCount, "LineCount" );
724 // border style
725 sal_Int16 nApiButton = AwtVisualEffect::LOOK3D;
726 sal_Int16 nApiBorder = AwtVisualEffect::LOOK3D;
727 switch( nClassId )
729 case FormCompType::LISTBOX:
730 case FormCompType::COMBOBOX:
731 aCtrlProp.GetProperty( nApiBorder, "Border" );
732 break;
733 case FormCompType::CHECKBOX:
734 case FormCompType::RADIOBUTTON:
735 aCtrlProp.GetProperty( nApiButton, "VisualEffect" );
736 nApiBorder = AwtVisualEffect::NONE;
737 break;
738 // Push button cannot be set to flat in Excel
739 case FormCompType::COMMANDBUTTON:
740 nApiBorder = AwtVisualEffect::LOOK3D;
741 break;
742 // Label does not support a border in Excel
743 case FormCompType::FIXEDTEXT:
744 nApiBorder = AwtVisualEffect::NONE;
745 break;
746 /* Scroll bar and spin button have a "Border" property, but it is
747 really used for a border, and not for own 3D/flat look (#i34712#). */
748 case FormCompType::SCROLLBAR:
749 case FormCompType::SPINBUTTON:
750 nApiButton = AwtVisualEffect::LOOK3D;
751 nApiBorder = AwtVisualEffect::NONE;
752 break;
753 // Group box does not support flat style (#i34712#)
754 case FormCompType::GROUPBOX:
755 nApiBorder = AwtVisualEffect::LOOK3D;
756 break;
758 mbFlatButton = nApiButton != AwtVisualEffect::LOOK3D;
759 mbFlatBorder = nApiBorder != AwtVisualEffect::LOOK3D;
761 // control state
762 sal_Int16 nApiState = 0;
763 if( aCtrlProp.GetProperty( nApiState, "State" ) )
765 switch( nApiState )
767 case 0: mnState = EXC_OBJ_CHECKBOX_UNCHECKED; break;
768 case 1: mnState = EXC_OBJ_CHECKBOX_CHECKED; break;
769 case 2: mnState = EXC_OBJ_CHECKBOX_TRISTATE; break;
773 // special control contents
774 switch( nClassId )
776 case FormCompType::LISTBOX:
778 mbMultiSel = aCtrlProp.GetBoolProperty( "MultiSelection" );
779 Sequence< sal_Int16 > aSelection;
780 if( aCtrlProp.GetProperty( aSelection, "SelectedItems" ) )
782 sal_Int32 nLen = aSelection.getLength();
783 if( nLen > 0 )
785 mnSelEntry = aSelection[ 0 ] + 1;
786 maMultiSel.resize( nLen );
787 const sal_Int16* pnBegin = aSelection.getConstArray();
788 ::std::copy( pnBegin, pnBegin + nLen, maMultiSel.begin() );
792 // convert listbox with dropdown button to Excel dropdown
793 if( aCtrlProp.GetBoolProperty( "Dropdown" ) )
794 mnObjType = EXC_OBJTYPE_DROPDOWN;
796 break;
798 case FormCompType::COMBOBOX:
800 Sequence< OUString > aStringList;
801 OUString aDefText;
802 if( aCtrlProp.GetProperty( aStringList, "StringItemList" ) &&
803 aCtrlProp.GetProperty( aDefText, "Text" ) &&
804 aStringList.getLength() && !aDefText.isEmpty() )
806 const OUString* pBegin = aStringList.getConstArray();
807 const OUString* pEnd = pBegin + aStringList.getLength();
808 const OUString* pString = ::std::find( pBegin, pEnd, aDefText );
809 if( pString != pEnd )
810 mnSelEntry = static_cast< sal_Int16 >( pString - pBegin + 1 ); // 1-based
811 if( mnSelEntry > 0 )
812 maMultiSel.resize( 1, mnSelEntry - 1 );
815 // convert combobox without dropdown button to Excel listbox
816 if( !aCtrlProp.GetBoolProperty( "Dropdown" ) )
817 mnObjType = EXC_OBJTYPE_LISTBOX;
819 break;
821 case FormCompType::SCROLLBAR:
823 sal_Int32 nApiValue = 0;
824 if( aCtrlProp.GetProperty( nApiValue, "ScrollValueMin" ) )
825 mnScrollMin = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
826 if( aCtrlProp.GetProperty( nApiValue, "ScrollValueMax" ) )
827 mnScrollMax = limit_cast< sal_uInt16 >( nApiValue, mnScrollMin, EXC_OBJ_SCROLLBAR_MIN );
828 if( aCtrlProp.GetProperty( nApiValue, "ScrollValue" ) )
829 mnScrollValue = limit_cast< sal_uInt16 >( nApiValue, mnScrollMin, mnScrollMax );
830 if( aCtrlProp.GetProperty( nApiValue, "LineIncrement" ) )
831 mnScrollStep = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
832 if( aCtrlProp.GetProperty( nApiValue, "BlockIncrement" ) )
833 mnScrollPage = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
834 if( aCtrlProp.GetProperty( nApiValue, "Orientation" ) )
835 mbScrollHor = nApiValue == AwtScrollOrient::HORIZONTAL;
837 break;
839 case FormCompType::SPINBUTTON:
841 sal_Int32 nApiValue = 0;
842 if( aCtrlProp.GetProperty( nApiValue, "SpinValueMin" ) )
843 mnScrollMin = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
844 if( aCtrlProp.GetProperty( nApiValue, "SpinValueMax" ) )
845 mnScrollMax = limit_cast< sal_uInt16 >( nApiValue, mnScrollMin, EXC_OBJ_SCROLLBAR_MAX );
846 if( aCtrlProp.GetProperty( nApiValue, "SpinValue" ) )
847 mnScrollValue = limit_cast< sal_uInt16 >( nApiValue, mnScrollMin, mnScrollMax );
848 if( aCtrlProp.GetProperty( nApiValue, "SpinIncrement" ) )
849 mnScrollStep = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
850 if( aCtrlProp.GetProperty( nApiValue, "Orientation" ) )
851 mbScrollHor = nApiValue == AwtScrollOrient::HORIZONTAL;
853 break;
856 // spreadsheet links
857 ConvertSheetLinks( xShape );
860 bool XclExpTbxControlObj::SetMacroLink( const ScriptEventDescriptor& rEvent )
862 return XclMacroHelper::SetMacroLink( rEvent, meEventType );
865 void XclExpTbxControlObj::WriteSubRecs( XclExpStream& rStrm )
867 switch( mnObjType )
869 // *** Push buttons, labels ***
871 case EXC_OBJTYPE_BUTTON:
872 case EXC_OBJTYPE_LABEL:
873 // ftMacro - macro link
874 WriteMacroSubRec( rStrm );
875 break;
877 // *** Check boxes, option buttons ***
879 case EXC_OBJTYPE_CHECKBOX:
880 case EXC_OBJTYPE_OPTIONBUTTON:
882 // ftCbls - box properties
883 sal_uInt16 nStyle = 0;
884 ::set_flag( nStyle, EXC_OBJ_CHECKBOX_FLAT, mbFlatButton );
886 rStrm.StartRecord( EXC_ID_OBJCBLS, 12 );
887 rStrm << mnState;
888 rStrm.WriteZeroBytes( 8 );
889 rStrm << nStyle;
890 rStrm.EndRecord();
892 // ftMacro - macro link
893 WriteMacroSubRec( rStrm );
894 // ftCblsFmla subrecord - cell link
895 WriteCellLinkSubRec( rStrm, EXC_ID_OBJCBLSFMLA );
897 // ftCblsData subrecord - box properties, again
898 rStrm.StartRecord( EXC_ID_OBJCBLS, 8 );
899 rStrm << mnState;
900 rStrm.WriteZeroBytes( 4 );
901 rStrm << nStyle;
902 rStrm.EndRecord();
904 break;
906 // *** List boxes, combo boxes ***
908 case EXC_OBJTYPE_LISTBOX:
909 case EXC_OBJTYPE_DROPDOWN:
911 sal_uInt16 nEntryCount = GetSourceEntryCount();
913 // ftSbs subrecord - Scroll bars
914 sal_Int32 nLineHeight = XclTools::GetHmmFromTwips( 200 ); // always 10pt
915 if( mnObjType == EXC_OBJTYPE_LISTBOX )
916 mnLineCount = static_cast< sal_uInt16 >( mnHeight / nLineHeight );
917 mnScrollValue = 0;
918 mnScrollMin = 0;
919 sal_uInt16 nInvisLines = (nEntryCount >= mnLineCount) ? (nEntryCount - mnLineCount) : 0;
920 mnScrollMax = limit_cast< sal_uInt16 >( nInvisLines, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
921 mnScrollStep = 1;
922 mnScrollPage = limit_cast< sal_uInt16 >( mnLineCount, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
923 mbScrollHor = false;
924 WriteSbs( rStrm );
926 // ftMacro - macro link
927 WriteMacroSubRec( rStrm );
928 // ftSbsFmla subrecord - cell link
929 WriteCellLinkSubRec( rStrm, EXC_ID_OBJSBSFMLA );
931 // ftLbsData - source data range and box properties
932 sal_uInt16 nStyle = 0;
933 ::insert_value( nStyle, mbMultiSel ? EXC_OBJ_LISTBOX_MULTI : EXC_OBJ_LISTBOX_SINGLE, 4, 2 );
934 ::set_flag( nStyle, EXC_OBJ_LISTBOX_FLAT, mbFlatBorder );
936 rStrm.StartRecord( EXC_ID_OBJLBSDATA, 0 );
938 if( const XclTokenArray* pSrcRange = GetSourceRangeTokArr() )
940 rStrm << static_cast< sal_uInt16 >( (pSrcRange->GetSize() + 7) & 0xFFFE );
941 WriteFormula( rStrm, *pSrcRange );
943 else
944 rStrm << sal_uInt16( 0 );
946 rStrm << nEntryCount << mnSelEntry << nStyle << sal_uInt16( 0 );
947 if( mnObjType == EXC_OBJTYPE_LISTBOX )
949 if( nEntryCount )
951 ScfUInt8Vec aSelEx( nEntryCount, 0 );
952 for( ScfInt16Vec::const_iterator aIt = maMultiSel.begin(), aEnd = maMultiSel.end(); aIt != aEnd; ++aIt )
953 if( *aIt < nEntryCount )
954 aSelEx[ *aIt ] = 1;
955 rStrm.Write( &aSelEx[ 0 ], aSelEx.size() );
958 else if( mnObjType == EXC_OBJTYPE_DROPDOWN )
960 rStrm << sal_uInt16( 0 ) << mnLineCount << sal_uInt16( 0 ) << sal_uInt16( 0 );
963 rStrm.EndRecord();
965 break;
967 // *** Spin buttons, scrollbars ***
969 case EXC_OBJTYPE_SPIN:
970 case EXC_OBJTYPE_SCROLLBAR:
972 // ftSbs subrecord - scroll bars
973 WriteSbs( rStrm );
974 // ftMacro - macro link
975 WriteMacroSubRec( rStrm );
976 // ftSbsFmla subrecord - cell link
977 WriteCellLinkSubRec( rStrm, EXC_ID_OBJSBSFMLA );
979 break;
981 // *** Group boxes ***
983 case EXC_OBJTYPE_GROUPBOX:
985 // ftMacro - macro link
986 WriteMacroSubRec( rStrm );
988 // ftGboData subrecord - group box properties
989 sal_uInt16 nStyle = 0;
990 ::set_flag( nStyle, EXC_OBJ_GROUPBOX_FLAT, mbFlatBorder );
992 rStrm.StartRecord( EXC_ID_OBJGBODATA, 6 );
993 rStrm << sal_uInt32( 0 )
994 << nStyle;
995 rStrm.EndRecord();
997 break;
1001 void XclExpTbxControlObj::WriteCellLinkSubRec( XclExpStream& rStrm, sal_uInt16 nSubRecId )
1003 if( const XclTokenArray* pCellLink = GetCellLinkTokArr() )
1004 WriteFormulaSubRec( rStrm, nSubRecId, *pCellLink );
1007 void XclExpTbxControlObj::WriteSbs( XclExpStream& rStrm )
1009 sal_uInt16 nOrient = 0;
1010 ::set_flag( nOrient, EXC_OBJ_SCROLLBAR_HOR, mbScrollHor );
1011 sal_uInt16 nStyle = EXC_OBJ_SCROLLBAR_DEFFLAGS;
1012 ::set_flag( nStyle, EXC_OBJ_SCROLLBAR_FLAT, mbFlatButton );
1014 rStrm.StartRecord( EXC_ID_OBJSBS, 20 );
1015 rStrm << sal_uInt32( 0 ) // reserved
1016 << mnScrollValue // thumb position
1017 << mnScrollMin // thumb min pos
1018 << mnScrollMax // thumb max pos
1019 << mnScrollStep // line increment
1020 << mnScrollPage // page increment
1021 << nOrient // 0 = vertical, 1 = horizontal
1022 << sal_uInt16( 15 ) // thumb width
1023 << nStyle; // flags/style
1024 rStrm.EndRecord();
1027 //#endif
1029 XclExpChartObj::XclExpChartObj( XclExpObjectManager& rObjMgr, Reference< XShape > xShape, const Rectangle* pChildAnchor ) :
1030 XclObj( rObjMgr, EXC_OBJTYPE_CHART ),
1031 XclExpRoot( rObjMgr.GetRoot() ), mxShape( xShape )
1033 // create the MSODRAWING record contents for the chart object
1034 mrEscherEx.OpenContainer( ESCHER_SpContainer );
1035 mrEscherEx.AddShape( ESCHER_ShpInst_HostControl, SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_HAVESPT );
1036 EscherPropertyContainer aPropOpt;
1037 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x01040104 );
1038 aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x00080008 );
1039 aPropOpt.AddOpt( ESCHER_Prop_fillColor, 0x0800004E );
1040 aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x0800004D );
1041 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x00110010 );
1042 aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x0800004D );
1043 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080008 );
1044 aPropOpt.AddOpt( ESCHER_Prop_fshadowObscured, 0x00020000 );
1045 aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x00080000 );
1046 aPropOpt.Commit( mrEscherEx.GetStream() );
1048 // anchor
1049 SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape( xShape );
1050 ImplWriteAnchor( GetRoot(), pSdrObj, pChildAnchor );
1052 // client data (the following OBJ record)
1053 mrEscherEx.AddAtom( 0, ESCHER_ClientData );
1054 mrEscherEx.CloseContainer(); // ESCHER_SpContainer
1055 mrEscherEx.UpdateDffFragmentEnd();
1057 // load the chart OLE object
1058 if( SdrOle2Obj* pSdrOleObj = dynamic_cast< SdrOle2Obj* >( pSdrObj ) )
1059 svt::EmbeddedObjectRef::TryRunningState( pSdrOleObj->GetObjRef() );
1061 // create the chart substream object
1062 ScfPropertySet aShapeProp( xShape );
1063 Reference< XModel > xModel;
1064 aShapeProp.GetProperty( xModel, "Model" );
1065 mxChartDoc.set( xModel,UNO_QUERY );
1066 ::com::sun::star::awt::Rectangle aBoundRect;
1067 aShapeProp.GetProperty( aBoundRect, "BoundRect" );
1068 Rectangle aChartRect( Point( aBoundRect.X, aBoundRect.Y ), Size( aBoundRect.Width, aBoundRect.Height ) );
1069 mxChart.reset( new XclExpChart( GetRoot(), xModel, aChartRect ) );
1072 XclExpChartObj::~XclExpChartObj()
1076 void XclExpChartObj::Save( XclExpStream& rStrm )
1078 // content of OBJ record
1079 XclObj::Save( rStrm );
1080 // chart substream
1081 mxChart->Save( rStrm );
1084 void XclExpChartObj::SaveXml( XclExpXmlStream& rStrm )
1086 OSL_TRACE("XclExpChartObj::SaveXml -- Entry point to export chart");
1087 sax_fastparser::FSHelperPtr pDrawing = rStrm.GetCurrentStream();
1089 // FIXME: two cell? it seems the two cell anchor is incorrect.
1090 pDrawing->startElement( FSNS( XML_xdr, XML_twoCellAnchor ), // OOXTODO: oneCellAnchor, absoluteAnchor
1091 XML_editAs, "oneCell",
1092 FSEND );
1093 Reference< XPropertySet > xPropSet( mxShape, UNO_QUERY );
1094 if (xPropSet.is())
1096 XclObjAny::WriteFromTo( rStrm, mxShape, GetTab() );
1097 Reference< XModel > xModel( mxChartDoc, UNO_QUERY );
1098 ChartExport aChartExport( XML_xdr, pDrawing, xModel, &rStrm, DrawingML::DOCUMENT_XLSX );
1099 static sal_Int32 nChartCount = 0;
1100 nChartCount++;
1101 aChartExport.WriteChartObj( mxShape, nChartCount );
1102 // TODO: get the correcto chart number
1105 pDrawing->singleElement( FSNS( XML_xdr, XML_clientData),
1106 // OOXTODO: XML_fLocksWithSheet
1107 // OOXTODO: XML_fPrintsWithSheet
1108 FSEND );
1109 pDrawing->endElement( FSNS( XML_xdr, XML_twoCellAnchor ) );
1112 const css::uno::Reference<css::chart::XChartDocument>& XclExpChartObj::GetChartDoc() const
1114 return mxChartDoc;
1117 XclExpNote::XclExpNote( const XclExpRoot& rRoot, const ScAddress& rScPos,
1118 const ScPostIt* pScNote, const OUString& rAddText ) :
1119 XclExpRecord( EXC_ID_NOTE ),
1120 maScPos( rScPos ),
1121 mnObjId( EXC_OBJ_INVALID_ID ),
1122 mbVisible( pScNote && pScNote->IsCaptionShown() )
1124 // get the main note text
1125 OUString aNoteText;
1126 if( pScNote )
1128 aNoteText = pScNote->GetText();
1129 const EditTextObject *pEditObj = pScNote->GetEditTextObject();
1130 if( pEditObj )
1131 mpNoteContents = XclExpStringHelper::CreateString( rRoot, *pEditObj );
1133 // append additional text
1134 aNoteText = ScGlobal::addToken( aNoteText, rAddText, '\n', 2 );
1135 maOrigNoteText = aNoteText;
1137 // initialize record dependent on BIFF type
1138 switch( rRoot.GetBiff() )
1140 case EXC_BIFF5:
1141 maNoteText = OUStringToOString(aNoteText, rRoot.GetTextEncoding());
1142 break;
1144 case EXC_BIFF8:
1146 // TODO: additional text
1147 if( pScNote )
1148 if( SdrCaptionObj* pCaption = pScNote->GetOrCreateCaption( maScPos ) )
1150 lcl_GetFromTo( rRoot, pCaption->GetLogicRect(), maScPos.Tab(), maCommentFrom, maCommentTo );
1151 if( const OutlinerParaObject* pOPO = pCaption->GetOutlinerParaObject() )
1152 mnObjId = rRoot.GetObjectManager().AddObj( new XclObjComment( rRoot.GetObjectManager(), pCaption->GetLogicRect(), pOPO->GetTextObject(), pCaption, mbVisible, maScPos, maCommentFrom, maCommentTo ) );
1154 SfxItemSet aItemSet = pCaption->GetMergedItemSet();
1155 meTVA = pCaption->GetTextVerticalAdjust();
1156 meTHA = pCaption->GetTextHorizontalAdjust();
1157 mbAutoScale = pCaption->GetFitToSize() != SDRTEXTFIT_NONE;
1158 mbLocked = pCaption->IsMoveProtect() || pCaption->IsResizeProtect();
1160 // AutoFill style would change if Postit.cxx object creation values are changed
1161 OUString aCol(((XFillColorItem &)GETITEM(aItemSet, XFillColorItem , XATTR_FILLCOLOR)).GetValue());
1162 mbAutoFill = aCol.isEmpty() && (GETITEMVALUE(aItemSet, XFillStyleItem, XATTR_FILLSTYLE, sal_uLong) == drawing::FillStyle_SOLID);
1163 mbAutoLine = true;
1164 mbRowHidden = (rRoot.GetDoc().RowHidden(maScPos.Row(),maScPos.Tab()));
1165 mbColHidden = (rRoot.GetDoc().ColHidden(maScPos.Col(),maScPos.Tab()));
1168 SetRecSize( 9 + maAuthor.GetSize() );
1170 break;
1172 default: DBG_ERROR_BIFF();
1176 void XclExpNote::Save( XclExpStream& rStrm )
1178 switch( rStrm.GetRoot().GetBiff() )
1180 case EXC_BIFF5:
1182 // write the NOTE record directly, there may be the need to create more than one
1183 const sal_Char* pcBuffer = maNoteText.getStr();
1184 sal_uInt16 nCharsLeft = static_cast< sal_uInt16 >( maNoteText.getLength() );
1186 while( nCharsLeft )
1188 sal_uInt16 nWriteChars = ::std::min( nCharsLeft, EXC_NOTE5_MAXLEN );
1190 rStrm.StartRecord( EXC_ID_NOTE, 6 + nWriteChars );
1191 if( pcBuffer == maNoteText.getStr() )
1193 // first record: row, col, length of complete text
1194 rStrm << static_cast< sal_uInt16 >( maScPos.Row() )
1195 << static_cast< sal_uInt16 >( maScPos.Col() )
1196 << nCharsLeft; // still contains full length
1198 else
1200 // next records: -1, 0, length of current text segment
1201 rStrm << sal_uInt16( 0xFFFF )
1202 << sal_uInt16( 0 )
1203 << nWriteChars;
1205 rStrm.Write( pcBuffer, nWriteChars );
1206 rStrm.EndRecord();
1208 pcBuffer += nWriteChars;
1209 nCharsLeft = nCharsLeft - nWriteChars;
1212 break;
1214 case EXC_BIFF8:
1215 if( mnObjId != EXC_OBJ_INVALID_ID )
1216 XclExpRecord::Save( rStrm );
1217 break;
1219 default: DBG_ERROR_BIFF();
1223 void XclExpNote::WriteBody( XclExpStream& rStrm )
1225 // BIFF5/BIFF7 is written separately
1226 OSL_ENSURE_BIFF( rStrm.GetRoot().GetBiff() == EXC_BIFF8 );
1228 sal_uInt16 nFlags = 0;
1229 ::set_flag( nFlags, EXC_NOTE_VISIBLE, mbVisible );
1231 rStrm << static_cast< sal_uInt16 >( maScPos.Row() )
1232 << static_cast< sal_uInt16 >( maScPos.Col() )
1233 << nFlags
1234 << mnObjId
1235 << maAuthor
1236 << sal_uInt8( 0 );
1239 void XclExpNote::WriteXml( sal_Int32 nAuthorId, XclExpXmlStream& rStrm )
1241 sax_fastparser::FSHelperPtr rComments = rStrm.GetCurrentStream();
1243 rComments->startElement( XML_comment,
1244 XML_ref, XclXmlUtils::ToOString( maScPos ).getStr(),
1245 XML_authorId, OString::number( nAuthorId ).getStr(),
1246 // OOXTODO: XML_guid,
1247 FSEND );
1248 rComments->startElement( XML_text, FSEND );
1249 // OOXTODO: phoneticPr, rPh, r
1250 if( mpNoteContents )
1251 mpNoteContents->WriteXml( rStrm );
1252 rComments->endElement( XML_text );
1255 Export of commentPr is disabled, since the current (Oct 2010)
1256 version of MSO 2010 doesn't yet support commentPr
1258 #if 1//def XLSX_OOXML_FUTURE
1259 if( rStrm.getVersion() == oox::core::ISOIEC_29500_2008 )
1261 rComments->startElement( FSNS( XML_mc, XML_AlternateContent ), FSEND );
1262 rComments->startElement( FSNS( XML_mc, XML_Choice ), XML_Requires, "v2", FSEND );
1263 rComments->startElement( XML_commentPr,
1264 XML_autoFill, XclXmlUtils::ToPsz( mbAutoFill ),
1265 XML_autoScale, XclXmlUtils::ToPsz( mbAutoScale ),
1266 XML_colHidden, XclXmlUtils::ToPsz( mbColHidden ),
1267 XML_locked, XclXmlUtils::ToPsz( mbLocked ),
1268 XML_rowHidden, XclXmlUtils::ToPsz( mbRowHidden ),
1269 XML_textHAlign, ToHorizAlign( meTHA ),
1270 XML_textVAlign, ToVertAlign( meTVA ) ,
1271 FSEND );
1272 rComments->startElement( XML_anchor,
1273 XML_moveWithCells, "false",
1274 XML_sizeWithCells, "false",
1275 FSEND );
1276 rComments->startElement( FSNS( XML_xdr, XML_from ), FSEND );
1277 lcl_WriteAnchorVertex( rComments, maCommentFrom );
1278 rComments->endElement( FSNS( XML_xdr, XML_from ) );
1279 rComments->startElement( FSNS( XML_xdr, XML_to ), FSEND );
1280 lcl_WriteAnchorVertex( rComments, maCommentTo );
1281 rComments->endElement( FSNS( XML_xdr, XML_to ) );
1282 rComments->endElement( XML_anchor );
1283 rComments->endElement( XML_commentPr );
1285 rComments->endElement( FSNS( XML_mc, XML_Choice ) );
1286 rComments->startElement( FSNS( XML_mc, XML_Fallback ), FSEND );
1287 // Any fallback code ?
1288 rComments->endElement( FSNS( XML_mc, XML_Fallback ) );
1289 rComments->endElement( FSNS( XML_mc, XML_AlternateContent ) );
1291 #endif
1292 rComments->endElement( XML_comment );
1295 XclMacroHelper::XclMacroHelper( const XclExpRoot& rRoot ) :
1296 XclExpControlHelper( rRoot )
1300 XclMacroHelper::~XclMacroHelper()
1304 void XclMacroHelper::WriteMacroSubRec( XclExpStream& rStrm )
1306 if( mxMacroLink )
1307 WriteFormulaSubRec( rStrm, EXC_ID_OBJMACRO, *mxMacroLink );
1310 bool
1311 XclMacroHelper::SetMacroLink( const ScriptEventDescriptor& rEvent, const XclTbxEventType& nEventType )
1313 OUString aMacroName = XclControlHelper::ExtractFromMacroDescriptor( rEvent, nEventType, GetDocShell() );
1314 if( !aMacroName.isEmpty() )
1316 return SetMacroLink( aMacroName );
1318 return false;
1321 bool
1322 XclMacroHelper::SetMacroLink( const OUString& rMacroName )
1324 OSL_TRACE("SetMacroLink( macroname:=%s )", OUStringToOString( rMacroName, RTL_TEXTENCODING_UTF8 ).getStr() );
1325 if( !rMacroName.isEmpty() )
1327 sal_uInt16 nExtSheet = GetLocalLinkManager().FindExtSheet( EXC_EXTSH_OWNDOC );
1328 sal_uInt16 nNameIdx = GetNameManager().InsertMacroCall( rMacroName, true, false );
1329 mxMacroLink = GetFormulaCompiler().CreateNameXFormula( nExtSheet, nNameIdx );
1330 return true;
1332 return false;
1335 XclExpShapeObj::XclExpShapeObj( XclExpObjectManager& rRoot, ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape ) :
1336 XclObjAny( rRoot, xShape ),
1337 XclMacroHelper( rRoot )
1339 if( SdrObject* pSdrObj = ::GetSdrObjectFromXShape( xShape ) )
1341 ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( pSdrObj );
1342 if ( pInfo && !pInfo->GetMacro().isEmpty() )
1343 // FIXME ooo330-m2: XclControlHelper::GetXclMacroName was removed in upstream sources; they started to call XclTools::GetXclMacroName instead; is this enough? it has only one parameter
1344 // SetMacroLink( XclControlHelper::GetXclMacroName( pInfo->GetMacro(), rRoot.GetDocShell() ) );
1345 SetMacroLink( XclTools::GetXclMacroName( pInfo->GetMacro() ) );
1349 XclExpShapeObj::~XclExpShapeObj()
1353 void XclExpShapeObj::WriteSubRecs( XclExpStream& rStrm )
1355 XclObjAny::WriteSubRecs( rStrm );
1356 WriteMacroSubRec( rStrm );
1359 XclExpComments::XclExpComments( SCTAB nTab, XclExpRecordList< XclExpNote >& rNotes )
1360 : mnTab( nTab ), mrNotes( rNotes )
1364 struct OUStringLess : public std::binary_function<OUString, OUString, bool>
1366 bool operator()(const OUString& x, const OUString& y) const
1368 return x.compareTo( y ) < 0;
1372 void XclExpComments::SaveXml( XclExpXmlStream& rStrm )
1374 if( mrNotes.IsEmpty() )
1375 return;
1377 sax_fastparser::FSHelperPtr rComments = rStrm.CreateOutputStream(
1378 XclXmlUtils::GetStreamName( "xl/", "comments", mnTab + 1 ),
1379 XclXmlUtils::GetStreamName( "../", "comments", mnTab + 1 ),
1380 rStrm.GetCurrentStream()->getOutputStream(),
1381 "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml",
1382 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments" );
1383 rStrm.PushStream( rComments );
1385 if( rStrm.getVersion() == oox::core::ISOIEC_29500_2008 )
1386 rComments->startElement( XML_comments,
1387 XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
1388 FSNS( XML_xmlns, XML_mc ), "http://schemas.openxmlformats.org/markup-compatibility/2006",
1389 FSNS( XML_xmlns, XML_xdr ), "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing",
1390 FSNS( XML_xmlns, XML_v2 ), "http://schemas.openxmlformats.org/spreadsheetml/2006/main/v2",
1391 FSNS( XML_mc, XML_Ignorable ), "v2",
1392 FSEND );
1393 else
1394 rComments->startElement( XML_comments,
1395 XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
1396 FSNS( XML_xmlns, XML_xdr ), "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing",
1397 FSEND );
1399 rComments->startElement( XML_authors, FSEND );
1401 typedef std::set< OUString, OUStringLess > Authors;
1402 Authors aAuthors;
1404 size_t nNotes = mrNotes.GetSize();
1405 for( size_t i = 0; i < nNotes; ++i )
1407 aAuthors.insert( XclXmlUtils::ToOUString( mrNotes.GetRecord( i )->GetAuthor() ) );
1410 for( Authors::const_iterator b = aAuthors.begin(), e = aAuthors.end(); b != e; ++b )
1412 rComments->startElement( XML_author, FSEND );
1413 rComments->writeEscaped( *b );
1414 rComments->endElement( XML_author );
1417 rComments->endElement( XML_authors );
1418 rComments->startElement( XML_commentList, FSEND );
1420 Authors::const_iterator aAuthorsBegin = aAuthors.begin();
1421 for( size_t i = 0; i < nNotes; ++i )
1423 XclExpNoteList::RecordRefType xNote = mrNotes.GetRecord( i );
1424 Authors::const_iterator aAuthor = aAuthors.find(
1425 XclXmlUtils::ToOUString( xNote->GetAuthor() ) );
1426 sal_Int32 nAuthorId = distance( aAuthorsBegin, aAuthor );
1427 xNote->WriteXml( nAuthorId, rStrm );
1430 rComments->endElement( XML_commentList );
1431 rComments->endElement( XML_comments );
1433 rStrm.PopStream();
1436 // object manager =============================================================
1438 XclExpObjectManager::XclExpObjectManager( const XclExpRoot& rRoot ) :
1439 XclExpRoot( rRoot )
1441 InitStream( true );
1442 mxEscherEx.reset( new XclEscherEx( GetRoot(), *this, *mxDffStrm ) );
1445 XclExpObjectManager::XclExpObjectManager( const XclExpObjectManager& rParent ) :
1446 XclExpRoot( rParent.GetRoot() )
1448 InitStream( false );
1449 mxEscherEx.reset( new XclEscherEx( GetRoot(), *this, *mxDffStrm, rParent.mxEscherEx.get() ) );
1452 XclExpObjectManager::~XclExpObjectManager()
1456 XclExpDffAnchorBase* XclExpObjectManager::CreateDffAnchor() const
1458 return new XclExpDffSheetAnchor( GetRoot() );
1461 std::shared_ptr< XclExpRecordBase > XclExpObjectManager::CreateDrawingGroup()
1463 return std::shared_ptr< XclExpRecordBase >( new XclExpMsoDrawingGroup( *mxEscherEx ) );
1466 void XclExpObjectManager::StartSheet()
1468 mxObjList.reset( new XclExpObjList( GetRoot(), *mxEscherEx ) );
1471 std::shared_ptr< XclExpRecordBase > XclExpObjectManager::ProcessDrawing( SdrPage* pSdrPage )
1473 if( pSdrPage )
1474 mxEscherEx->AddSdrPage( *pSdrPage );
1475 // the first dummy object may still be open
1476 OSL_ENSURE( mxEscherEx->GetGroupLevel() <= 1, "XclExpObjectManager::ProcessDrawing - still groups open?" );
1477 while( mxEscherEx->GetGroupLevel() )
1478 mxEscherEx->LeaveGroup();
1479 mxObjList->EndSheet();
1480 return mxObjList;
1483 std::shared_ptr< XclExpRecordBase > XclExpObjectManager::ProcessDrawing( const Reference< XShapes >& rxShapes )
1485 if( rxShapes.is() )
1486 mxEscherEx->AddUnoShapes( rxShapes );
1487 // the first dummy object may still be open
1488 OSL_ENSURE( mxEscherEx->GetGroupLevel() <= 1, "XclExpObjectManager::ProcessDrawing - still groups open?" );
1489 while( mxEscherEx->GetGroupLevel() )
1490 mxEscherEx->LeaveGroup();
1491 mxObjList->EndSheet();
1492 return mxObjList;
1495 void XclExpObjectManager::EndDocument()
1497 mxEscherEx->EndDocument();
1500 XclExpMsoDrawing* XclExpObjectManager::GetMsodrawingPerSheet()
1502 return mxObjList->GetMsodrawingPerSheet();
1505 bool XclExpObjectManager::HasObj() const
1507 return !mxObjList->empty();
1510 sal_uInt16 XclExpObjectManager::AddObj( XclObj* pObjRec )
1512 return mxObjList->Add( pObjRec );
1515 XclObj* XclExpObjectManager::RemoveLastObj()
1517 XclObj* pLastObj = mxObjList->back();
1518 mxObjList->pop_back();
1519 return pLastObj;
1522 void XclExpObjectManager::InitStream( bool bTempFile )
1524 if( bTempFile )
1526 mxTempFile.reset( new ::utl::TempFile );
1527 if( mxTempFile->IsValid() )
1529 mxTempFile->EnableKillingFile();
1530 mxDffStrm.reset( ::utl::UcbStreamHelper::CreateStream( mxTempFile->GetURL(), STREAM_STD_READWRITE ) );
1534 if( !mxDffStrm.get() )
1535 mxDffStrm.reset( new SvMemoryStream );
1537 mxDffStrm->SetEndian( SvStreamEndian::LITTLE );
1540 XclExpEmbeddedObjectManager::XclExpEmbeddedObjectManager(
1541 const XclExpObjectManager& rParent, const Size& rPageSize, sal_Int32 nScaleX, sal_Int32 nScaleY ) :
1542 XclExpObjectManager( rParent ),
1543 maPageSize( rPageSize ),
1544 mnScaleX( nScaleX ),
1545 mnScaleY( nScaleY )
1549 XclExpDffAnchorBase* XclExpEmbeddedObjectManager::CreateDffAnchor() const
1551 return new XclExpDffEmbeddedAnchor( GetRoot(), maPageSize, mnScaleX, mnScaleY );
1554 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */