Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / sc / source / filter / excel / xeescher.cxx
blob8859baac227edeed343e5ecdc272721a8f4a62b6
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/XListEntrySink.hpp>
30 #include <com/sun/star/script/ScriptEventDescriptor.hpp>
31 #include <com/sun/star/chart2/XChartDocument.hpp>
32 #include <com/sun/star/awt/Point.hpp>
33 #include <com/sun/star/awt/Size.hpp>
35 #include <set>
36 #include <rtl/ustrbuf.h>
37 #include <vcl/bitmapaccess.hxx>
38 #include <svx/svdoole2.hxx>
39 #include <svx/svdocapt.hxx>
40 #include <editeng/outlobj.hxx>
41 #include <editeng/editobj.hxx>
42 #include <unotools/tempfile.hxx>
43 #include <unotools/ucbstreamhelper.hxx>
44 #include <svtools/embedhlp.hxx>
46 #include "editutil.hxx"
47 #include "unonames.hxx"
48 #include "convuno.hxx"
49 #include "postit.hxx"
51 #include "fapihelper.hxx"
52 #include "xechart.hxx"
53 #include "xeformula.hxx"
54 #include "xelink.hxx"
55 #include "xename.hxx"
56 #include "xestyle.hxx"
57 #include "userdat.hxx"
58 #include "drwlayer.hxx"
59 #include <svx/unoapi.hxx>
60 #include <svx/algitem.hxx>
61 #include "scitems.hxx"
62 #include <editeng/justifyitem.hxx>
63 #include <svx/sdtaitm.hxx>
64 #include "attrib.hxx"
65 #include "document.hxx"
66 #include <svx/svdattr.hxx>
67 #include <svx/sdr/properties/properties.hxx>
68 #include "detfunc.hxx"
69 #include <svx/xflclit.hxx>
70 #include <svx/xlnstwit.hxx>
71 #include <svx/xlnstit.hxx>
73 #include <oox/token/tokens.hxx>
74 #include <oox/export/drawingml.hxx>
75 #include <oox/export/chartexport.hxx>
76 #include <oox/export/utils.hxx>
77 #include <memory>
79 using namespace com::sun::star;
80 using ::com::sun::star::uno::UNO_QUERY;
81 using ::com::sun::star::uno::Reference;
82 using ::com::sun::star::uno::Sequence;
83 using ::com::sun::star::lang::XServiceInfo;
84 using ::com::sun::star::beans::XPropertySet;
85 using ::com::sun::star::drawing::XShape;
86 using ::com::sun::star::drawing::XShapes;
87 using ::com::sun::star::frame::XModel;
88 using ::com::sun::star::awt::XControlModel;
89 using ::com::sun::star::form::binding::XBindableValue;
90 using ::com::sun::star::form::binding::XListEntrySink;
91 using ::com::sun::star::script::ScriptEventDescriptor;
92 using ::com::sun::star::table::CellAddress;
93 using ::com::sun::star::table::CellRangeAddress;
94 using ::com::sun::star::chart2::XChartDocument;
95 using ::oox::drawingml::DrawingML;
96 using ::oox::drawingml::ChartExport;
97 using namespace oox;
99 namespace
102 inline long lcl_hmm2px(long nPixel)
104 return static_cast<long>(nPixel*PIXEL_PER_INCH/1000.0/CM_PER_INCH)+0.5;
107 const char *ToHorizAlign( SdrTextHorzAdjust eAdjust )
109 switch( eAdjust )
111 case SDRTEXTHORZADJUST_CENTER:
112 return "center";
113 case SDRTEXTHORZADJUST_RIGHT:
114 return "right";
115 case SDRTEXTHORZADJUST_BLOCK:
116 return "justify";
117 case SDRTEXTHORZADJUST_LEFT:
118 default:
119 return "left";
123 const char *ToVertAlign( SdrTextVertAdjust eAdjust )
125 switch( eAdjust )
127 case SDRTEXTVERTADJUST_CENTER:
128 return "center";
129 case SDRTEXTVERTADJUST_BOTTOM:
130 return "bottom";
131 case SDRTEXTVERTADJUST_BLOCK:
132 return "justify";
133 case SDRTEXTVERTADJUST_TOP:
134 default:
135 return "top";
139 void lcl_WriteAnchorVertex( sax_fastparser::FSHelperPtr rComments, Rectangle &aRect )
141 rComments->startElement( FSNS( XML_xdr, XML_col ), FSEND );
142 rComments->writeEscaped( OUString::number( aRect.Left() ) );
143 rComments->endElement( FSNS( XML_xdr, XML_col ) );
144 rComments->startElement( FSNS( XML_xdr, XML_colOff ), FSEND );
145 rComments->writeEscaped( OUString::number( aRect.Top() ) );
146 rComments->endElement( FSNS( XML_xdr, XML_colOff ) );
147 rComments->startElement( FSNS( XML_xdr, XML_row ), FSEND );
148 rComments->writeEscaped( OUString::number( aRect.Right() ) );
149 rComments->endElement( FSNS( XML_xdr, XML_row ) );
150 rComments->startElement( FSNS( XML_xdr, XML_rowOff ), FSEND );
151 rComments->writeEscaped( OUString::number( aRect.Bottom() ) );
152 rComments->endElement( FSNS( XML_xdr, XML_rowOff ) );
155 void lcl_GetFromTo( const XclExpRoot& rRoot, const Rectangle &aRect, sal_Int32 nTab, Rectangle &aFrom, Rectangle &aTo )
157 sal_Int32 nCol = 0, nRow = 0;
158 sal_Int32 nColOff = 0, nRowOff= 0;
160 const bool bRTL = rRoot.GetDocRef().IsNegativePage( nTab );
161 if (!bRTL)
163 while(true)
165 Rectangle r = rRoot.GetDocRef().GetMMRect( nCol,nRow,nCol,nRow,nTab );
166 if( r.Left() <= aRect.Left() )
168 nCol++;
169 nColOff = aRect.Left() - r.Left();
171 if( r.Top() <= aRect.Top() )
173 nRow++;
174 nRowOff = aRect.Top() - r.Top();
176 if( r.Left() > aRect.Left() && r.Top() > aRect.Top() )
178 aFrom = Rectangle( nCol-1, lcl_hmm2px( nColOff ),
179 nRow-1, lcl_hmm2px( nRowOff ) );
180 break;
184 else
186 while(true)
188 Rectangle r = rRoot.GetDocRef().GetMMRect( nCol,nRow,nCol,nRow,nTab );
189 if( r.Left() >= aRect.Left() )
191 nCol++;
192 nColOff = r.Left() - aRect.Left();
194 if( r.Top() <= aRect.Top() )
196 nRow++;
197 nRowOff = aRect.Top() - r.Top();
199 if( r.Left() < aRect.Left() && r.Top() > aRect.Top() )
201 aFrom = Rectangle( nCol-1, lcl_hmm2px( nColOff ),
202 nRow-1, lcl_hmm2px( nRowOff ) );
203 break;
207 if (!bRTL)
209 while(true)
211 Rectangle r = rRoot.GetDocRef().GetMMRect( nCol,nRow,nCol,nRow,nTab );
212 if( r.Right() < aRect.Right() )
213 nCol++;
214 if( r.Bottom() < aRect.Bottom() )
215 nRow++;
216 if( r.Right() >= aRect.Right() && r.Bottom() >= aRect.Bottom() )
218 aTo = Rectangle( nCol, lcl_hmm2px( aRect.Right() - r.Left() ),
219 nRow, lcl_hmm2px( aRect.Bottom() - r.Top() ));
220 break;
224 else
226 while(true)
228 Rectangle r = rRoot.GetDocRef().GetMMRect( nCol,nRow,nCol,nRow,nTab );
229 if( r.Right() >= aRect.Right() )
230 nCol++;
231 if( r.Bottom() < aRect.Bottom() )
232 nRow++;
233 if( r.Right() < aRect.Right() && r.Bottom() >= aRect.Bottom() )
235 aTo = Rectangle( nCol, lcl_hmm2px( r.Left() - aRect.Right() ),
236 nRow, lcl_hmm2px( aRect.Bottom() - r.Top() ));
237 break;
243 } // namespace
245 // Escher client anchor =======================================================
247 XclExpDffAnchorBase::XclExpDffAnchorBase( const XclExpRoot& rRoot, sal_uInt16 nFlags ) :
248 XclExpRoot( rRoot ),
249 mnFlags( nFlags )
253 void XclExpDffAnchorBase::SetFlags( const SdrObject& rSdrObj )
255 ImplSetFlags( rSdrObj );
258 void XclExpDffAnchorBase::SetSdrObject( const SdrObject& rSdrObj )
260 ImplSetFlags( rSdrObj );
261 ImplCalcAnchorRect( rSdrObj.GetCurrentBoundRect(), MAP_100TH_MM );
264 void XclExpDffAnchorBase::WriteDffData( EscherEx& rEscherEx ) const
266 rEscherEx.AddAtom( 18, ESCHER_ClientAnchor );
267 rEscherEx.GetStream().WriteUInt16( mnFlags );
268 WriteXclObjAnchor( rEscherEx.GetStream(), maAnchor );
271 void XclExpDffAnchorBase::WriteData( EscherEx& rEscherEx, const Rectangle& rRect )
273 // the passed rectangle is in twips
274 ImplCalcAnchorRect( rRect, MAP_TWIP );
275 WriteDffData( rEscherEx );
278 void XclExpDffAnchorBase::ImplSetFlags( const SdrObject& )
280 OSL_FAIL( "XclExpDffAnchorBase::ImplSetFlags - not implemented" );
283 void XclExpDffAnchorBase::ImplCalcAnchorRect( const Rectangle&, MapUnit )
285 OSL_FAIL( "XclExpDffAnchorBase::ImplCalcAnchorRect - not implemented" );
288 XclExpDffSheetAnchor::XclExpDffSheetAnchor( const XclExpRoot& rRoot ) :
289 XclExpDffAnchorBase( rRoot ),
290 mnScTab( rRoot.GetCurrScTab() )
294 void XclExpDffSheetAnchor::ImplSetFlags( const SdrObject& rSdrObj )
296 // set flags for cell/page anchoring
297 if ( ScDrawLayer::GetAnchorType( rSdrObj ) == SCA_CELL )
298 mnFlags = 0;
299 else
300 mnFlags = EXC_ESC_ANCHOR_LOCKED;
303 void XclExpDffSheetAnchor::ImplCalcAnchorRect( const Rectangle& rRect, MapUnit eMapUnit )
305 maAnchor.SetRect( GetRoot(), mnScTab, rRect, eMapUnit );
308 XclExpDffEmbeddedAnchor::XclExpDffEmbeddedAnchor( const XclExpRoot& rRoot,
309 const Size& rPageSize, sal_Int32 nScaleX, sal_Int32 nScaleY ) :
310 XclExpDffAnchorBase( rRoot ),
311 maPageSize( rPageSize ),
312 mnScaleX( nScaleX ),
313 mnScaleY( nScaleY )
317 void XclExpDffEmbeddedAnchor::ImplSetFlags( const SdrObject& /*rSdrObj*/ )
319 // TODO (unsupported feature): fixed size
322 void XclExpDffEmbeddedAnchor::ImplCalcAnchorRect( const Rectangle& rRect, MapUnit eMapUnit )
324 maAnchor.SetRect( maPageSize, mnScaleX, mnScaleY, rRect, eMapUnit );
327 XclExpDffNoteAnchor::XclExpDffNoteAnchor( const XclExpRoot& rRoot, const Rectangle& rRect ) :
328 XclExpDffAnchorBase( rRoot, EXC_ESC_ANCHOR_SIZELOCKED )
330 maAnchor.SetRect( rRoot, rRoot.GetCurrScTab(), rRect, MAP_100TH_MM );
333 XclExpDffDropDownAnchor::XclExpDffDropDownAnchor( const XclExpRoot& rRoot, const ScAddress& rScPos ) :
334 XclExpDffAnchorBase( rRoot, EXC_ESC_ANCHOR_POSLOCKED )
336 GetAddressConverter().ConvertAddress( maAnchor.maFirst, rScPos, true );
337 maAnchor.maLast.mnCol = maAnchor.maFirst.mnCol + 1;
338 maAnchor.maLast.mnRow = maAnchor.maFirst.mnRow + 1;
339 maAnchor.mnLX = maAnchor.mnTY = maAnchor.mnRX = maAnchor.mnBY = 0;
342 // MSODRAWING* records ========================================================
344 XclExpMsoDrawingBase::XclExpMsoDrawingBase( XclEscherEx& rEscherEx, sal_uInt16 nRecId ) :
345 XclExpRecord( nRecId ),
346 mrEscherEx( rEscherEx ),
347 mnFragmentKey( rEscherEx.InitNextDffFragment() )
351 void XclExpMsoDrawingBase::WriteBody( XclExpStream& rStrm )
353 OSL_ENSURE( mrEscherEx.GetStreamPos() == mrEscherEx.GetDffFragmentPos( mnFragmentKey ),
354 "XclExpMsoDrawingBase::WriteBody - DFF stream position mismatch" );
355 rStrm.CopyFromStream( mrEscherEx.GetStream(), mrEscherEx.GetDffFragmentSize( mnFragmentKey ) );
358 XclExpMsoDrawingGroup::XclExpMsoDrawingGroup( XclEscherEx& rEscherEx ) :
359 XclExpMsoDrawingBase( rEscherEx, EXC_ID_MSODRAWINGGROUP )
361 SvStream& rDffStrm = mrEscherEx.GetStream();
363 // write the DGGCONTAINER with some default settings
364 mrEscherEx.OpenContainer( ESCHER_DggContainer );
366 // TODO: stuff the OPT atom with our own document defaults?
367 static const sal_uInt8 spnDffOpt[] = {
368 0xBF, 0x00, 0x08, 0x00, 0x08, 0x00, 0x81, 0x01,
369 0x09, 0x00, 0x00, 0x08, 0xC0, 0x01, 0x40, 0x00,
370 0x00, 0x08
372 mrEscherEx.AddAtom( sizeof( spnDffOpt ), ESCHER_OPT, 3, 3 );
373 rDffStrm.Write( spnDffOpt, sizeof( spnDffOpt ) );
375 // SPLITMENUCOLORS contains colors in toolbar
376 static const sal_uInt8 spnDffSplitMenuColors[] = {
377 0x0D, 0x00, 0x00, 0x08, 0x0C, 0x00, 0x00, 0x08,
378 0x17, 0x00, 0x00, 0x08, 0xF7, 0x00, 0x00, 0x10
380 mrEscherEx.AddAtom( sizeof( spnDffSplitMenuColors ), ESCHER_SplitMenuColors, 0, 4 );
381 rDffStrm.Write( spnDffSplitMenuColors, sizeof( spnDffSplitMenuColors ) );
383 // close the DGGCONTAINER
384 mrEscherEx.CloseContainer();
385 mrEscherEx.UpdateDffFragmentEnd();
388 XclExpMsoDrawing::XclExpMsoDrawing( XclEscherEx& rEscherEx ) :
389 XclExpMsoDrawingBase( rEscherEx, EXC_ID_MSODRAWING )
393 XclExpImgData::XclExpImgData( const Graphic& rGraphic, sal_uInt16 nRecId ) :
394 maGraphic( rGraphic ),
395 mnRecId( nRecId )
399 void XclExpImgData::Save( XclExpStream& rStrm )
401 Bitmap aBmp = maGraphic.GetBitmap();
402 if( aBmp.GetBitCount() != 24 )
403 aBmp.Convert( BMP_CONVERSION_24BIT );
405 if( BitmapReadAccess* pAccess = aBmp.AcquireReadAccess() )
407 sal_Int32 nWidth = ::std::min< sal_Int32 >( pAccess->Width(), 0xFFFF );
408 sal_Int32 nHeight = ::std::min< sal_Int32 >( pAccess->Height(), 0xFFFF );
409 if( (nWidth > 0) && (nHeight > 0) )
411 sal_uInt8 nPadding = static_cast< sal_uInt8 >( nWidth & 0x03 );
412 sal_uInt32 nTmpSize = static_cast< sal_uInt32 >( (nWidth * 3 + nPadding) * nHeight + 12 );
414 rStrm.StartRecord( mnRecId, nTmpSize + 4 );
416 rStrm << EXC_IMGDATA_BMP // BMP format
417 << EXC_IMGDATA_WIN // Windows
418 << nTmpSize // size after _this_ field
419 << sal_uInt32( 12 ) // BITMAPCOREHEADER size
420 << static_cast< sal_uInt16 >( nWidth ) // width
421 << static_cast< sal_uInt16 >( nHeight ) // height
422 << sal_uInt16( 1 ) // planes
423 << sal_uInt16( 24 ); // bits per pixel
425 for( sal_Int32 nY = nHeight - 1; nY >= 0; --nY )
427 for( sal_Int32 nX = 0; nX < nWidth; ++nX )
429 const BitmapColor& rBmpColor = pAccess->GetPixel( nY, nX );
430 rStrm << rBmpColor.GetBlue() << rBmpColor.GetGreen() << rBmpColor.GetRed();
432 rStrm.WriteZeroBytes( nPadding );
435 rStrm.EndRecord();
437 Bitmap::ReleaseAccess( pAccess );
441 void XclExpImgData::SaveXml( XclExpXmlStream& rStrm )
443 sax_fastparser::FSHelperPtr pWorksheet = rStrm.GetCurrentStream();
445 DrawingML aDML(pWorksheet, &rStrm, drawingml::DOCUMENT_XLSX);
446 OUString rId = aDML.WriteImage( maGraphic );
447 pWorksheet->singleElement( XML_picture,
448 FSNS( XML_r, XML_id ), XclXmlUtils::ToOString( rId ).getStr(),
449 FSEND );
452 XclExpControlHelper::XclExpControlHelper( const XclExpRoot& rRoot ) :
453 XclExpRoot( rRoot ),
454 mnEntryCount( 0 )
458 XclExpControlHelper::~XclExpControlHelper()
462 void XclExpControlHelper::ConvertSheetLinks( Reference< XShape > xShape )
464 mxCellLink.reset();
465 mxSrcRange.reset();
466 mnEntryCount = 0;
468 // get control model
469 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( xShape );
470 if( !xCtrlModel.is() )
471 return;
473 // *** cell link *** ------------------------------------------------------
475 Reference< XBindableValue > xBindable( xCtrlModel, UNO_QUERY );
476 if( xBindable.is() )
478 Reference< XServiceInfo > xServInfo( xBindable->getValueBinding(), UNO_QUERY );
479 if( xServInfo.is() && xServInfo->supportsService( SC_SERVICENAME_VALBIND ) )
481 ScfPropertySet aBindProp( xServInfo );
482 CellAddress aApiAddress;
483 if( aBindProp.GetProperty( aApiAddress, SC_UNONAME_BOUNDCELL ) )
485 ScAddress aCellLink;
486 ScUnoConversion::FillScAddress( aCellLink, aApiAddress );
487 if( GetTabInfo().IsExportTab( aCellLink.Tab() ) )
488 mxCellLink = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CONTROL, aCellLink );
493 // *** source range *** ---------------------------------------------------
495 Reference< XListEntrySink > xEntrySink( xCtrlModel, UNO_QUERY );
496 if( xEntrySink.is() )
498 Reference< XServiceInfo > xServInfo( xEntrySink->getListEntrySource(), UNO_QUERY );
499 if( xServInfo.is() && xServInfo->supportsService( SC_SERVICENAME_LISTSOURCE ) )
501 ScfPropertySet aSinkProp( xServInfo );
502 CellRangeAddress aApiRange;
503 if( aSinkProp.GetProperty( aApiRange, SC_UNONAME_CELLRANGE ) )
505 ScRange aSrcRange;
506 ScUnoConversion::FillScRange( aSrcRange, aApiRange );
507 if( (aSrcRange.aStart.Tab() == aSrcRange.aEnd.Tab()) && GetTabInfo().IsExportTab( aSrcRange.aStart.Tab() ) )
508 mxSrcRange = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CONTROL, aSrcRange );
509 mnEntryCount = static_cast< sal_uInt16 >( aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1 );
515 void XclExpControlHelper::WriteFormula( XclExpStream& rStrm, const XclTokenArray& rTokArr )
517 sal_uInt16 nFmlaSize = rTokArr.GetSize();
518 rStrm << nFmlaSize << sal_uInt32( 0 );
519 rTokArr.WriteArray( rStrm );
520 if( nFmlaSize & 1 ) // pad to 16-bit
521 rStrm << sal_uInt8( 0 );
524 void XclExpControlHelper::WriteFormulaSubRec( XclExpStream& rStrm, sal_uInt16 nSubRecId, const XclTokenArray& rTokArr )
526 rStrm.StartRecord( nSubRecId, (rTokArr.GetSize() + 5) & ~1 );
527 WriteFormula( rStrm, rTokArr );
528 rStrm.EndRecord();
531 //delete for exporting OCX
532 //#if EXC_EXP_OCX_CTRL
534 XclExpOcxControlObj::XclExpOcxControlObj( XclExpObjectManager& rObjMgr, Reference< XShape > xShape,
535 const Rectangle* pChildAnchor, const OUString& rClassName, sal_uInt32 nStrmStart, sal_uInt32 nStrmSize ) :
536 XclObj( rObjMgr, EXC_OBJTYPE_PICTURE, true ),
537 XclExpControlHelper( rObjMgr.GetRoot() ),
538 maClassName( rClassName ),
539 mnStrmStart( nStrmStart ),
540 mnStrmSize( nStrmSize )
542 ScfPropertySet aCtrlProp( XclControlHelper::GetControlModel( xShape ) );
544 // OBJ record flags
545 SetLocked( true );
546 SetPrintable( aCtrlProp.GetBoolProperty( "Printable" ) );
547 SetAutoFill( false );
548 SetAutoLine( false );
550 // fill DFF property set
551 mrEscherEx.OpenContainer( ESCHER_SpContainer );
552 mrEscherEx.AddShape( ESCHER_ShpInst_HostControl, SHAPEFLAG_HAVESPT | SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_OLESHAPE );
553 Rectangle aDummyRect;
554 EscherPropertyContainer aPropOpt( mrEscherEx.GetGraphicProvider(), mrEscherEx.QueryPictureStream(), aDummyRect );
555 aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x00080008 ); // bool field
556 aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x08000040 );
557 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080000 ); // bool field
559 // #i51348# name of the control, may overwrite shape name
560 OUString aCtrlName;
561 if( aCtrlProp.GetProperty( aCtrlName, "Name" ) && !aCtrlName.isEmpty() )
562 aPropOpt.AddOpt( ESCHER_Prop_wzName, aCtrlName );
564 // meta file
565 //TODO - needs check
566 Reference< XPropertySet > xShapePS( xShape, UNO_QUERY );
567 if( xShapePS.is() && aPropOpt.CreateGraphicProperties( xShapePS, "MetaFile", false ) )
569 sal_uInt32 nBlipId;
570 if( aPropOpt.GetOpt( ESCHER_Prop_pib, nBlipId ) )
571 aPropOpt.AddOpt( ESCHER_Prop_pictureId, nBlipId );
574 // write DFF property set to stream
575 aPropOpt.Commit( mrEscherEx.GetStream() );
577 // anchor
578 ImplWriteAnchor( GetRoot(), SdrObject::getSdrObjectFromXShape( xShape ), pChildAnchor );
580 mrEscherEx.AddAtom( 0, ESCHER_ClientData ); // OBJ record
581 mrEscherEx.CloseContainer(); // ESCHER_SpContainer
582 mrEscherEx.UpdateDffFragmentEnd();
584 // spreadsheet links
585 ConvertSheetLinks( xShape );
588 void XclExpOcxControlObj::WriteSubRecs( XclExpStream& rStrm )
590 // OBJCF - clipboard format
591 rStrm.StartRecord( EXC_ID_OBJCF, 2 );
592 rStrm << sal_uInt16( 2 );
593 rStrm.EndRecord();
595 // OBJFLAGS
596 rStrm.StartRecord( EXC_ID_OBJFLAGS, 2 );
597 rStrm << sal_uInt16( 0x0031 );
598 rStrm.EndRecord();
600 // OBJPICTFMLA
601 XclExpString aClass( maClassName );
602 sal_uInt16 nClassNameSize = static_cast< sal_uInt16 >( aClass.GetSize() );
603 sal_uInt16 nClassNamePad = nClassNameSize & 1;
604 sal_uInt16 nFirstPartSize = 12 + nClassNameSize + nClassNamePad;
606 const XclTokenArray* pCellLink = GetCellLinkTokArr();
607 sal_uInt16 nCellLinkSize = pCellLink ? ((pCellLink->GetSize() + 7) & 0xFFFE) : 0;
609 const XclTokenArray* pSrcRange = GetSourceRangeTokArr();
610 sal_uInt16 nSrcRangeSize = pSrcRange ? ((pSrcRange->GetSize() + 7) & 0xFFFE) : 0;
612 sal_uInt16 nPictFmlaSize = nFirstPartSize + nCellLinkSize + nSrcRangeSize + 18;
613 rStrm.StartRecord( EXC_ID_OBJPICTFMLA, nPictFmlaSize );
615 rStrm << sal_uInt16( nFirstPartSize ) // size of first part
616 << sal_uInt16( 5 ) // formula size
617 << sal_uInt32( 0 ) // unknown ID
618 << sal_uInt8( 0x02 ) << sal_uInt32( 0 ) // tTbl token with unknown ID
619 << sal_uInt8( 3 ) // pad to word
620 << aClass; // "Forms.***.1"
621 rStrm.WriteZeroBytes( nClassNamePad ); // pad to word
622 rStrm << mnStrmStart // start in 'Ctls' stream
623 << mnStrmSize // size in 'Ctls' stream
624 << sal_uInt32( 0 ); // class ID size
625 // cell link
626 rStrm << nCellLinkSize;
627 if( pCellLink )
628 WriteFormula( rStrm, *pCellLink );
629 // list source range
630 rStrm << nSrcRangeSize;
631 if( pSrcRange )
632 WriteFormula( rStrm, *pSrcRange );
634 rStrm.EndRecord();
637 //#else
639 XclExpTbxControlObj::XclExpTbxControlObj( XclExpObjectManager& rRoot, Reference< XShape > xShape , const Rectangle* pChildAnchor ) :
640 XclObj( rRoot, EXC_OBJTYPE_UNKNOWN, true ),
641 XclMacroHelper( rRoot ),
642 meEventType( EXC_TBX_EVENT_ACTION ),
643 mnHeight( 0 ),
644 mnState( 0 ),
645 mnLineCount( 0 ),
646 mnSelEntry( 0 ),
647 mnScrollValue( 0 ),
648 mnScrollMin( 0 ),
649 mnScrollMax( 100 ),
650 mnScrollStep( 1 ),
651 mnScrollPage( 10 ),
652 mbFlatButton( false ),
653 mbFlatBorder( false ),
654 mbMultiSel( false ),
655 mbScrollHor( false )
657 namespace FormCompType = css::form::FormComponentType;
658 namespace AwtVisualEffect = css::awt::VisualEffect;
659 namespace AwtScrollOrient = css::awt::ScrollBarOrientation;
661 ScfPropertySet aCtrlProp( XclControlHelper::GetControlModel( xShape ) );
662 if( !xShape.is() || !aCtrlProp.Is() )
663 return;
665 mnHeight = xShape->getSize().Height;
666 if( mnHeight <= 0 )
667 return;
669 // control type
670 sal_Int16 nClassId = 0;
671 if( aCtrlProp.GetProperty( nClassId, "ClassId" ) )
673 switch( nClassId )
675 case FormCompType::COMMANDBUTTON: mnObjType = EXC_OBJTYPE_BUTTON; meEventType = EXC_TBX_EVENT_ACTION; break;
676 case FormCompType::RADIOBUTTON: mnObjType = EXC_OBJTYPE_OPTIONBUTTON; meEventType = EXC_TBX_EVENT_ACTION; break;
677 case FormCompType::CHECKBOX: mnObjType = EXC_OBJTYPE_CHECKBOX; meEventType = EXC_TBX_EVENT_ACTION; break;
678 case FormCompType::LISTBOX: mnObjType = EXC_OBJTYPE_LISTBOX; meEventType = EXC_TBX_EVENT_CHANGE; break;
679 case FormCompType::COMBOBOX: mnObjType = EXC_OBJTYPE_DROPDOWN; meEventType = EXC_TBX_EVENT_CHANGE; break;
680 case FormCompType::GROUPBOX: mnObjType = EXC_OBJTYPE_GROUPBOX; meEventType = EXC_TBX_EVENT_MOUSE; break;
681 case FormCompType::FIXEDTEXT: mnObjType = EXC_OBJTYPE_LABEL; meEventType = EXC_TBX_EVENT_MOUSE; break;
682 case FormCompType::SCROLLBAR: mnObjType = EXC_OBJTYPE_SCROLLBAR; meEventType = EXC_TBX_EVENT_VALUE; break;
683 case FormCompType::SPINBUTTON: mnObjType = EXC_OBJTYPE_SPIN; meEventType = EXC_TBX_EVENT_VALUE; break;
686 if( mnObjType == EXC_OBJTYPE_UNKNOWN )
687 return;
689 // OBJ record flags
690 SetLocked( true );
691 SetPrintable( aCtrlProp.GetBoolProperty( "Printable" ) );
692 SetAutoFill( false );
693 SetAutoLine( false );
695 // fill DFF property set
696 mrEscherEx.OpenContainer( ESCHER_SpContainer );
697 mrEscherEx.AddShape( ESCHER_ShpInst_HostControl, SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_HAVESPT );
698 EscherPropertyContainer aPropOpt;
699 bool bVisible = aCtrlProp.GetBoolProperty( "EnableVisible" );
700 aPropOpt.AddOpt( ESCHER_Prop_fPrint, bVisible ? 0x00080000 : 0x00080002 ); // visible flag
702 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x01000100 ); // bool field
703 aPropOpt.AddOpt( ESCHER_Prop_lTxid, 0 ); // Text ID
704 aPropOpt.AddOpt( ESCHER_Prop_WrapText, 0x00000001 );
705 aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x001A0008 ); // bool field
706 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x00100000 ); // bool field
707 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080000 ); // bool field
709 // #i51348# name of the control, may overwrite shape name
710 OUString aCtrlName;
711 if( aCtrlProp.GetProperty( aCtrlName, "Name" ) && !aCtrlName.isEmpty() )
712 aPropOpt.AddOpt( ESCHER_Prop_wzName, aCtrlName );
714 //Export description as alt text
715 if( SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape( xShape ) )
717 OUString aAltTxt;
718 OUString aDescrText = pSdrObj->GetDescription();
719 if(!aDescrText.isEmpty())
720 aAltTxt = aDescrText.copy( 0, std::min<sal_Int32>(MSPROP_DESCRIPTION_MAX_LEN, aDescrText.getLength()) );
721 aPropOpt.AddOpt( ESCHER_Prop_wzDescription, aAltTxt );
724 // write DFF property set to stream
725 aPropOpt.Commit( mrEscherEx.GetStream() );
727 // anchor
728 ImplWriteAnchor( GetRoot(), SdrObject::getSdrObjectFromXShape( xShape ), pChildAnchor );
730 mrEscherEx.AddAtom( 0, ESCHER_ClientData ); // OBJ record
731 mrEscherEx.UpdateDffFragmentEnd();
733 // control label
734 OUString aString;
735 if( aCtrlProp.GetProperty( aString, "Label" ) )
737 /* Be sure to construct the MSODRAWING record containing the
738 ClientTextbox atom after the base OBJ's MSODRAWING record data is
739 completed. */
740 pClientTextbox = new XclExpMsoDrawing( mrEscherEx );
741 mrEscherEx.AddAtom( 0, ESCHER_ClientTextbox ); // TXO record
742 mrEscherEx.UpdateDffFragmentEnd();
744 sal_uInt16 nXclFont = EXC_FONT_APP;
745 if( !aString.isEmpty() )
747 XclFontData aFontData;
748 GetFontPropSetHelper().ReadFontProperties( aFontData, aCtrlProp, EXC_FONTPROPSET_CONTROL );
749 if( (!aFontData.maName.isEmpty() ) && (aFontData.mnHeight > 0) )
750 nXclFont = GetFontBuffer().Insert( aFontData, EXC_COLOR_CTRLTEXT );
753 pTxo = new XclTxo( aString, nXclFont );
754 pTxo->SetHorAlign( (mnObjType == EXC_OBJTYPE_BUTTON) ? EXC_OBJ_HOR_CENTER : EXC_OBJ_HOR_LEFT );
755 pTxo->SetVerAlign( EXC_OBJ_VER_CENTER );
758 mrEscherEx.CloseContainer(); // ESCHER_SpContainer
760 // other properties
761 aCtrlProp.GetProperty( mnLineCount, "LineCount" );
763 // border style
764 sal_Int16 nApiButton = AwtVisualEffect::LOOK3D;
765 sal_Int16 nApiBorder = AwtVisualEffect::LOOK3D;
766 switch( nClassId )
768 case FormCompType::LISTBOX:
769 case FormCompType::COMBOBOX:
770 aCtrlProp.GetProperty( nApiBorder, "Border" );
771 break;
772 case FormCompType::CHECKBOX:
773 case FormCompType::RADIOBUTTON:
774 aCtrlProp.GetProperty( nApiButton, "VisualEffect" );
775 nApiBorder = AwtVisualEffect::NONE;
776 break;
777 // Push button cannot be set to flat in Excel
778 case FormCompType::COMMANDBUTTON:
779 nApiBorder = AwtVisualEffect::LOOK3D;
780 break;
781 // Label does not support a border in Excel
782 case FormCompType::FIXEDTEXT:
783 nApiBorder = AwtVisualEffect::NONE;
784 break;
785 /* Scroll bar and spin button have a "Border" property, but it is
786 really used for a border, and not for own 3D/flat look (#i34712#). */
787 case FormCompType::SCROLLBAR:
788 case FormCompType::SPINBUTTON:
789 nApiButton = AwtVisualEffect::LOOK3D;
790 nApiBorder = AwtVisualEffect::NONE;
791 break;
792 // Group box does not support flat style (#i34712#)
793 case FormCompType::GROUPBOX:
794 nApiBorder = AwtVisualEffect::LOOK3D;
795 break;
797 mbFlatButton = nApiButton != AwtVisualEffect::LOOK3D;
798 mbFlatBorder = nApiBorder != AwtVisualEffect::LOOK3D;
800 // control state
801 sal_Int16 nApiState = 0;
802 if( aCtrlProp.GetProperty( nApiState, "State" ) )
804 switch( nApiState )
806 case 0: mnState = EXC_OBJ_CHECKBOX_UNCHECKED; break;
807 case 1: mnState = EXC_OBJ_CHECKBOX_CHECKED; break;
808 case 2: mnState = EXC_OBJ_CHECKBOX_TRISTATE; break;
812 // special control contents
813 switch( nClassId )
815 case FormCompType::LISTBOX:
817 mbMultiSel = aCtrlProp.GetBoolProperty( "MultiSelection" );
818 Sequence< sal_Int16 > aSelection;
819 if( aCtrlProp.GetProperty( aSelection, "SelectedItems" ) )
821 sal_Int32 nLen = aSelection.getLength();
822 if( nLen > 0 )
824 mnSelEntry = aSelection[ 0 ] + 1;
825 maMultiSel.resize( nLen );
826 const sal_Int16* pnBegin = aSelection.getConstArray();
827 ::std::copy( pnBegin, pnBegin + nLen, maMultiSel.begin() );
831 // convert listbox with dropdown button to Excel dropdown
832 if( aCtrlProp.GetBoolProperty( "Dropdown" ) )
833 mnObjType = EXC_OBJTYPE_DROPDOWN;
835 break;
837 case FormCompType::COMBOBOX:
839 Sequence< OUString > aStringList;
840 OUString aDefText;
841 if( aCtrlProp.GetProperty( aStringList, "StringItemList" ) &&
842 aCtrlProp.GetProperty( aDefText, "Text" ) &&
843 aStringList.getLength() && !aDefText.isEmpty() )
845 const OUString* pBegin = aStringList.getConstArray();
846 const OUString* pEnd = pBegin + aStringList.getLength();
847 const OUString* pString = ::std::find( pBegin, pEnd, aDefText );
848 if( pString != pEnd )
849 mnSelEntry = static_cast< sal_Int16 >( pString - pBegin + 1 ); // 1-based
850 if( mnSelEntry > 0 )
851 maMultiSel.resize( 1, mnSelEntry - 1 );
854 // convert combobox without dropdown button to Excel listbox
855 if( !aCtrlProp.GetBoolProperty( "Dropdown" ) )
856 mnObjType = EXC_OBJTYPE_LISTBOX;
858 break;
860 case FormCompType::SCROLLBAR:
862 sal_Int32 nApiValue = 0;
863 if( aCtrlProp.GetProperty( nApiValue, "ScrollValueMin" ) )
864 mnScrollMin = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
865 if( aCtrlProp.GetProperty( nApiValue, "ScrollValueMax" ) )
866 mnScrollMax = limit_cast< sal_uInt16 >( nApiValue, mnScrollMin, EXC_OBJ_SCROLLBAR_MIN );
867 if( aCtrlProp.GetProperty( nApiValue, "ScrollValue" ) )
868 mnScrollValue = limit_cast< sal_uInt16 >( nApiValue, mnScrollMin, mnScrollMax );
869 if( aCtrlProp.GetProperty( nApiValue, "LineIncrement" ) )
870 mnScrollStep = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
871 if( aCtrlProp.GetProperty( nApiValue, "BlockIncrement" ) )
872 mnScrollPage = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
873 if( aCtrlProp.GetProperty( nApiValue, "Orientation" ) )
874 mbScrollHor = nApiValue == AwtScrollOrient::HORIZONTAL;
876 break;
878 case FormCompType::SPINBUTTON:
880 sal_Int32 nApiValue = 0;
881 if( aCtrlProp.GetProperty( nApiValue, "SpinValueMin" ) )
882 mnScrollMin = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
883 if( aCtrlProp.GetProperty( nApiValue, "SpinValueMax" ) )
884 mnScrollMax = limit_cast< sal_uInt16 >( nApiValue, mnScrollMin, EXC_OBJ_SCROLLBAR_MAX );
885 if( aCtrlProp.GetProperty( nApiValue, "SpinValue" ) )
886 mnScrollValue = limit_cast< sal_uInt16 >( nApiValue, mnScrollMin, mnScrollMax );
887 if( aCtrlProp.GetProperty( nApiValue, "SpinIncrement" ) )
888 mnScrollStep = limit_cast< sal_uInt16 >( nApiValue, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
889 if( aCtrlProp.GetProperty( nApiValue, "Orientation" ) )
890 mbScrollHor = nApiValue == AwtScrollOrient::HORIZONTAL;
892 break;
895 // spreadsheet links
896 ConvertSheetLinks( xShape );
899 bool XclExpTbxControlObj::SetMacroLink( const ScriptEventDescriptor& rEvent )
901 return XclMacroHelper::SetMacroLink( rEvent, meEventType );
904 void XclExpTbxControlObj::WriteSubRecs( XclExpStream& rStrm )
906 switch( mnObjType )
908 // *** Push buttons, labels ***
910 case EXC_OBJTYPE_BUTTON:
911 case EXC_OBJTYPE_LABEL:
912 // ftMacro - macro link
913 WriteMacroSubRec( rStrm );
914 break;
916 // *** Check boxes, option buttons ***
918 case EXC_OBJTYPE_CHECKBOX:
919 case EXC_OBJTYPE_OPTIONBUTTON:
921 // ftCbls - box properties
922 sal_uInt16 nStyle = 0;
923 ::set_flag( nStyle, EXC_OBJ_CHECKBOX_FLAT, mbFlatButton );
925 rStrm.StartRecord( EXC_ID_OBJCBLS, 12 );
926 rStrm << mnState;
927 rStrm.WriteZeroBytes( 8 );
928 rStrm << nStyle;
929 rStrm.EndRecord();
931 // ftMacro - macro link
932 WriteMacroSubRec( rStrm );
933 // ftCblsFmla subrecord - cell link
934 WriteCellLinkSubRec( rStrm, EXC_ID_OBJCBLSFMLA );
936 // ftCblsData subrecord - box properties, again
937 rStrm.StartRecord( EXC_ID_OBJCBLS, 8 );
938 rStrm << mnState;
939 rStrm.WriteZeroBytes( 4 );
940 rStrm << nStyle;
941 rStrm.EndRecord();
943 break;
945 // *** List boxes, combo boxes ***
947 case EXC_OBJTYPE_LISTBOX:
948 case EXC_OBJTYPE_DROPDOWN:
950 sal_uInt16 nEntryCount = GetSourceEntryCount();
952 // ftSbs subrecord - Scroll bars
953 sal_Int32 nLineHeight = XclTools::GetHmmFromTwips( 200 ); // always 10pt
954 if( mnObjType == EXC_OBJTYPE_LISTBOX )
955 mnLineCount = static_cast< sal_uInt16 >( mnHeight / nLineHeight );
956 mnScrollValue = 0;
957 mnScrollMin = 0;
958 sal_uInt16 nInvisLines = (nEntryCount >= mnLineCount) ? (nEntryCount - mnLineCount) : 0;
959 mnScrollMax = limit_cast< sal_uInt16 >( nInvisLines, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
960 mnScrollStep = 1;
961 mnScrollPage = limit_cast< sal_uInt16 >( mnLineCount, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
962 mbScrollHor = false;
963 WriteSbs( rStrm );
965 // ftMacro - macro link
966 WriteMacroSubRec( rStrm );
967 // ftSbsFmla subrecord - cell link
968 WriteCellLinkSubRec( rStrm, EXC_ID_OBJSBSFMLA );
970 // ftLbsData - source data range and box properties
971 sal_uInt16 nStyle = 0;
972 ::insert_value( nStyle, mbMultiSel ? EXC_OBJ_LISTBOX_MULTI : EXC_OBJ_LISTBOX_SINGLE, 4, 2 );
973 ::set_flag( nStyle, EXC_OBJ_LISTBOX_FLAT, mbFlatBorder );
975 rStrm.StartRecord( EXC_ID_OBJLBSDATA, 0 );
977 if( const XclTokenArray* pSrcRange = GetSourceRangeTokArr() )
979 rStrm << static_cast< sal_uInt16 >( (pSrcRange->GetSize() + 7) & 0xFFFE );
980 WriteFormula( rStrm, *pSrcRange );
982 else
983 rStrm << sal_uInt16( 0 );
985 rStrm << nEntryCount << mnSelEntry << nStyle << sal_uInt16( 0 );
986 if( mnObjType == EXC_OBJTYPE_LISTBOX )
988 if( nEntryCount )
990 ScfUInt8Vec aSelEx( nEntryCount, 0 );
991 for( ScfInt16Vec::const_iterator aIt = maMultiSel.begin(), aEnd = maMultiSel.end(); aIt != aEnd; ++aIt )
992 if( *aIt < nEntryCount )
993 aSelEx[ *aIt ] = 1;
994 rStrm.Write( &aSelEx[ 0 ], aSelEx.size() );
997 else if( mnObjType == EXC_OBJTYPE_DROPDOWN )
999 rStrm << sal_uInt16( 0 ) << mnLineCount << sal_uInt16( 0 ) << sal_uInt16( 0 );
1002 rStrm.EndRecord();
1004 break;
1006 // *** Spin buttons, scrollbars ***
1008 case EXC_OBJTYPE_SPIN:
1009 case EXC_OBJTYPE_SCROLLBAR:
1011 // ftSbs subrecord - scroll bars
1012 WriteSbs( rStrm );
1013 // ftMacro - macro link
1014 WriteMacroSubRec( rStrm );
1015 // ftSbsFmla subrecord - cell link
1016 WriteCellLinkSubRec( rStrm, EXC_ID_OBJSBSFMLA );
1018 break;
1020 // *** Group boxes ***
1022 case EXC_OBJTYPE_GROUPBOX:
1024 // ftMacro - macro link
1025 WriteMacroSubRec( rStrm );
1027 // ftGboData subrecord - group box properties
1028 sal_uInt16 nStyle = 0;
1029 ::set_flag( nStyle, EXC_OBJ_GROUPBOX_FLAT, mbFlatBorder );
1031 rStrm.StartRecord( EXC_ID_OBJGBODATA, 6 );
1032 rStrm << sal_uInt32( 0 )
1033 << nStyle;
1034 rStrm.EndRecord();
1036 break;
1040 void XclExpTbxControlObj::WriteCellLinkSubRec( XclExpStream& rStrm, sal_uInt16 nSubRecId )
1042 if( const XclTokenArray* pCellLink = GetCellLinkTokArr() )
1043 WriteFormulaSubRec( rStrm, nSubRecId, *pCellLink );
1046 void XclExpTbxControlObj::WriteSbs( XclExpStream& rStrm )
1048 sal_uInt16 nOrient = 0;
1049 ::set_flag( nOrient, EXC_OBJ_SCROLLBAR_HOR, mbScrollHor );
1050 sal_uInt16 nStyle = EXC_OBJ_SCROLLBAR_DEFFLAGS;
1051 ::set_flag( nStyle, EXC_OBJ_SCROLLBAR_FLAT, mbFlatButton );
1053 rStrm.StartRecord( EXC_ID_OBJSBS, 20 );
1054 rStrm << sal_uInt32( 0 ) // reserved
1055 << mnScrollValue // thumb position
1056 << mnScrollMin // thumb min pos
1057 << mnScrollMax // thumb max pos
1058 << mnScrollStep // line increment
1059 << mnScrollPage // page increment
1060 << nOrient // 0 = vertical, 1 = horizontal
1061 << sal_uInt16( 15 ) // thumb width
1062 << nStyle; // flags/style
1063 rStrm.EndRecord();
1066 //#endif
1068 XclExpChartObj::XclExpChartObj( XclExpObjectManager& rObjMgr, Reference< XShape > xShape, const Rectangle* pChildAnchor ) :
1069 XclObj( rObjMgr, EXC_OBJTYPE_CHART ),
1070 XclExpRoot( rObjMgr.GetRoot() ), mxShape( xShape )
1072 // create the MSODRAWING record contents for the chart object
1073 mrEscherEx.OpenContainer( ESCHER_SpContainer );
1074 mrEscherEx.AddShape( ESCHER_ShpInst_HostControl, SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_HAVESPT );
1075 EscherPropertyContainer aPropOpt;
1076 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x01040104 );
1077 aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x00080008 );
1078 aPropOpt.AddOpt( ESCHER_Prop_fillColor, 0x0800004E );
1079 aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x0800004D );
1080 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x00110010 );
1081 aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x0800004D );
1082 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080008 );
1083 aPropOpt.AddOpt( ESCHER_Prop_fshadowObscured, 0x00020000 );
1084 aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x00080000 );
1085 aPropOpt.Commit( mrEscherEx.GetStream() );
1087 // anchor
1088 SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape( xShape );
1089 ImplWriteAnchor( GetRoot(), pSdrObj, pChildAnchor );
1091 // client data (the following OBJ record)
1092 mrEscherEx.AddAtom( 0, ESCHER_ClientData );
1093 mrEscherEx.CloseContainer(); // ESCHER_SpContainer
1094 mrEscherEx.UpdateDffFragmentEnd();
1096 // load the chart OLE object
1097 if( SdrOle2Obj* pSdrOleObj = dynamic_cast< SdrOle2Obj* >( pSdrObj ) )
1098 svt::EmbeddedObjectRef::TryRunningState( pSdrOleObj->GetObjRef() );
1100 // create the chart substream object
1101 ScfPropertySet aShapeProp( xShape );
1102 Reference< XModel > xModel;
1103 aShapeProp.GetProperty( xModel, "Model" );
1104 mxChartDoc.set( xModel,UNO_QUERY );
1105 css::awt::Rectangle aBoundRect;
1106 aShapeProp.GetProperty( aBoundRect, "BoundRect" );
1107 Rectangle aChartRect( Point( aBoundRect.X, aBoundRect.Y ), Size( aBoundRect.Width, aBoundRect.Height ) );
1108 mxChart.reset( new XclExpChart( GetRoot(), xModel, aChartRect ) );
1111 XclExpChartObj::~XclExpChartObj()
1115 void XclExpChartObj::Save( XclExpStream& rStrm )
1117 // content of OBJ record
1118 XclObj::Save( rStrm );
1119 // chart substream
1120 mxChart->Save( rStrm );
1123 void XclExpChartObj::SaveXml( XclExpXmlStream& rStrm )
1125 OSL_TRACE("XclExpChartObj::SaveXml -- Entry point to export chart");
1126 sax_fastparser::FSHelperPtr pDrawing = rStrm.GetCurrentStream();
1128 // FIXME: two cell? it seems the two cell anchor is incorrect.
1129 pDrawing->startElement( FSNS( XML_xdr, XML_twoCellAnchor ), // OOXTODO: oneCellAnchor, absoluteAnchor
1130 XML_editAs, "oneCell",
1131 FSEND );
1132 Reference< XPropertySet > xPropSet( mxShape, UNO_QUERY );
1133 if (xPropSet.is())
1135 XclObjAny::WriteFromTo( rStrm, mxShape, GetTab() );
1136 Reference< XModel > xModel( mxChartDoc, UNO_QUERY );
1137 ChartExport aChartExport(XML_xdr, pDrawing, xModel, &rStrm, drawingml::DOCUMENT_XLSX);
1138 static sal_Int32 nChartCount = 0;
1139 nChartCount++;
1140 aChartExport.WriteChartObj( mxShape, nChartCount );
1141 // TODO: get the correcto chart number
1144 pDrawing->singleElement( FSNS( XML_xdr, XML_clientData),
1145 // OOXTODO: XML_fLocksWithSheet
1146 // OOXTODO: XML_fPrintsWithSheet
1147 FSEND );
1148 pDrawing->endElement( FSNS( XML_xdr, XML_twoCellAnchor ) );
1151 const css::uno::Reference<css::chart::XChartDocument>& XclExpChartObj::GetChartDoc() const
1153 return mxChartDoc;
1156 XclExpNote::XclExpNote( const XclExpRoot& rRoot, const ScAddress& rScPos,
1157 const ScPostIt* pScNote, const OUString& rAddText ) :
1158 XclExpRecord( EXC_ID_NOTE ),
1159 maScPos( rScPos ),
1160 mnObjId( EXC_OBJ_INVALID_ID ),
1161 mbVisible( pScNote && pScNote->IsCaptionShown() )
1163 // get the main note text
1164 OUString aNoteText;
1165 if( pScNote )
1167 aNoteText = pScNote->GetText();
1168 const EditTextObject *pEditObj = pScNote->GetEditTextObject();
1169 if( pEditObj )
1170 mpNoteContents = XclExpStringHelper::CreateString( rRoot, *pEditObj );
1172 // append additional text
1173 aNoteText = ScGlobal::addToken( aNoteText, rAddText, '\n', 2 );
1174 maOrigNoteText = aNoteText;
1176 // initialize record dependent on BIFF type
1177 switch( rRoot.GetBiff() )
1179 case EXC_BIFF5:
1180 maNoteText = OUStringToOString(aNoteText, rRoot.GetTextEncoding());
1181 break;
1183 case EXC_BIFF8:
1185 // TODO: additional text
1186 if( pScNote )
1187 if( SdrCaptionObj* pCaption = pScNote->GetOrCreateCaption( maScPos ) )
1189 lcl_GetFromTo( rRoot, pCaption->GetLogicRect(), maScPos.Tab(), maCommentFrom, maCommentTo );
1190 if( const OutlinerParaObject* pOPO = pCaption->GetOutlinerParaObject() )
1191 mnObjId = rRoot.GetObjectManager().AddObj( new XclObjComment( rRoot.GetObjectManager(), pCaption->GetLogicRect(), pOPO->GetTextObject(), pCaption, mbVisible, maScPos, maCommentFrom, maCommentTo ) );
1193 SfxItemSet aItemSet = pCaption->GetMergedItemSet();
1194 meTVA = pCaption->GetTextVerticalAdjust();
1195 meTHA = pCaption->GetTextHorizontalAdjust();
1196 mbAutoScale = pCaption->GetFitToSize() != SDRTEXTFIT_NONE;
1197 mbLocked = pCaption->IsMoveProtect() || pCaption->IsResizeProtect();
1199 // AutoFill style would change if Postit.cxx object creation values are changed
1200 OUString aCol(((XFillColorItem &)GETITEM(aItemSet, XFillColorItem , XATTR_FILLCOLOR)).GetValue());
1201 mbAutoFill = aCol.isEmpty() && (GETITEMVALUE(aItemSet, XFillStyleItem, XATTR_FILLSTYLE, sal_uLong) == drawing::FillStyle_SOLID);
1202 mbAutoLine = true;
1203 mbRowHidden = (rRoot.GetDoc().RowHidden(maScPos.Row(),maScPos.Tab()));
1204 mbColHidden = (rRoot.GetDoc().ColHidden(maScPos.Col(),maScPos.Tab()));
1207 SetRecSize( 9 + maAuthor.GetSize() );
1209 break;
1211 default: DBG_ERROR_BIFF();
1215 void XclExpNote::Save( XclExpStream& rStrm )
1217 switch( rStrm.GetRoot().GetBiff() )
1219 case EXC_BIFF5:
1221 // write the NOTE record directly, there may be the need to create more than one
1222 const sal_Char* pcBuffer = maNoteText.getStr();
1223 sal_uInt16 nCharsLeft = static_cast< sal_uInt16 >( maNoteText.getLength() );
1225 while( nCharsLeft )
1227 sal_uInt16 nWriteChars = ::std::min( nCharsLeft, EXC_NOTE5_MAXLEN );
1229 rStrm.StartRecord( EXC_ID_NOTE, 6 + nWriteChars );
1230 if( pcBuffer == maNoteText.getStr() )
1232 // first record: row, col, length of complete text
1233 rStrm << static_cast< sal_uInt16 >( maScPos.Row() )
1234 << static_cast< sal_uInt16 >( maScPos.Col() )
1235 << nCharsLeft; // still contains full length
1237 else
1239 // next records: -1, 0, length of current text segment
1240 rStrm << sal_uInt16( 0xFFFF )
1241 << sal_uInt16( 0 )
1242 << nWriteChars;
1244 rStrm.Write( pcBuffer, nWriteChars );
1245 rStrm.EndRecord();
1247 pcBuffer += nWriteChars;
1248 nCharsLeft = nCharsLeft - nWriteChars;
1251 break;
1253 case EXC_BIFF8:
1254 if( mnObjId != EXC_OBJ_INVALID_ID )
1255 XclExpRecord::Save( rStrm );
1256 break;
1258 default: DBG_ERROR_BIFF();
1262 void XclExpNote::WriteBody( XclExpStream& rStrm )
1264 // BIFF5/BIFF7 is written separately
1265 OSL_ENSURE_BIFF( rStrm.GetRoot().GetBiff() == EXC_BIFF8 );
1267 sal_uInt16 nFlags = 0;
1268 ::set_flag( nFlags, EXC_NOTE_VISIBLE, mbVisible );
1270 rStrm << static_cast< sal_uInt16 >( maScPos.Row() )
1271 << static_cast< sal_uInt16 >( maScPos.Col() )
1272 << nFlags
1273 << mnObjId
1274 << maAuthor
1275 << sal_uInt8( 0 );
1278 void XclExpNote::WriteXml( sal_Int32 nAuthorId, XclExpXmlStream& rStrm )
1280 sax_fastparser::FSHelperPtr rComments = rStrm.GetCurrentStream();
1282 rComments->startElement( XML_comment,
1283 XML_ref, XclXmlUtils::ToOString( maScPos ).getStr(),
1284 XML_authorId, OString::number( nAuthorId ).getStr(),
1285 // OOXTODO: XML_guid,
1286 FSEND );
1287 rComments->startElement( XML_text, FSEND );
1288 // OOXTODO: phoneticPr, rPh, r
1289 if( mpNoteContents )
1290 mpNoteContents->WriteXml( rStrm );
1291 rComments->endElement( XML_text );
1294 Export of commentPr is disabled, since the current (Oct 2010)
1295 version of MSO 2010 doesn't yet support commentPr
1297 #if 1//def XLSX_OOXML_FUTURE
1298 if( rStrm.getVersion() == oox::core::ISOIEC_29500_2008 )
1300 rComments->startElement( FSNS( XML_mc, XML_AlternateContent ), FSEND );
1301 rComments->startElement( FSNS( XML_mc, XML_Choice ), XML_Requires, "v2", FSEND );
1302 rComments->startElement( XML_commentPr,
1303 XML_autoFill, XclXmlUtils::ToPsz( mbAutoFill ),
1304 XML_autoScale, XclXmlUtils::ToPsz( mbAutoScale ),
1305 XML_colHidden, XclXmlUtils::ToPsz( mbColHidden ),
1306 XML_locked, XclXmlUtils::ToPsz( mbLocked ),
1307 XML_rowHidden, XclXmlUtils::ToPsz( mbRowHidden ),
1308 XML_textHAlign, ToHorizAlign( meTHA ),
1309 XML_textVAlign, ToVertAlign( meTVA ) ,
1310 FSEND );
1311 rComments->startElement( XML_anchor,
1312 XML_moveWithCells, "false",
1313 XML_sizeWithCells, "false",
1314 FSEND );
1315 rComments->startElement( FSNS( XML_xdr, XML_from ), FSEND );
1316 lcl_WriteAnchorVertex( rComments, maCommentFrom );
1317 rComments->endElement( FSNS( XML_xdr, XML_from ) );
1318 rComments->startElement( FSNS( XML_xdr, XML_to ), FSEND );
1319 lcl_WriteAnchorVertex( rComments, maCommentTo );
1320 rComments->endElement( FSNS( XML_xdr, XML_to ) );
1321 rComments->endElement( XML_anchor );
1322 rComments->endElement( XML_commentPr );
1324 rComments->endElement( FSNS( XML_mc, XML_Choice ) );
1325 rComments->startElement( FSNS( XML_mc, XML_Fallback ), FSEND );
1326 // Any fallback code ?
1327 rComments->endElement( FSNS( XML_mc, XML_Fallback ) );
1328 rComments->endElement( FSNS( XML_mc, XML_AlternateContent ) );
1330 #endif
1331 rComments->endElement( XML_comment );
1334 XclMacroHelper::XclMacroHelper( const XclExpRoot& rRoot ) :
1335 XclExpControlHelper( rRoot )
1339 XclMacroHelper::~XclMacroHelper()
1343 void XclMacroHelper::WriteMacroSubRec( XclExpStream& rStrm )
1345 if( mxMacroLink )
1346 WriteFormulaSubRec( rStrm, EXC_ID_OBJMACRO, *mxMacroLink );
1349 bool
1350 XclMacroHelper::SetMacroLink( const ScriptEventDescriptor& rEvent, const XclTbxEventType& nEventType )
1352 OUString aMacroName = XclControlHelper::ExtractFromMacroDescriptor( rEvent, nEventType, GetDocShell() );
1353 if( !aMacroName.isEmpty() )
1355 return SetMacroLink( aMacroName );
1357 return false;
1360 bool
1361 XclMacroHelper::SetMacroLink( const OUString& rMacroName )
1363 OSL_TRACE("SetMacroLink( macroname:=%s )", OUStringToOString( rMacroName, RTL_TEXTENCODING_UTF8 ).getStr() );
1364 if( !rMacroName.isEmpty() )
1366 sal_uInt16 nExtSheet = GetLocalLinkManager().FindExtSheet( EXC_EXTSH_OWNDOC );
1367 sal_uInt16 nNameIdx = GetNameManager().InsertMacroCall( rMacroName, true, false );
1368 mxMacroLink = GetFormulaCompiler().CreateNameXFormula( nExtSheet, nNameIdx );
1369 return true;
1371 return false;
1374 XclExpShapeObj::XclExpShapeObj( XclExpObjectManager& rRoot, css::uno::Reference< css::drawing::XShape > xShape, ScDocument* pDoc ) :
1375 XclObjAny( rRoot, xShape, pDoc ),
1376 XclMacroHelper( rRoot )
1378 if( SdrObject* pSdrObj = ::GetSdrObjectFromXShape( xShape ) )
1380 ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( pSdrObj );
1381 if ( pInfo && !pInfo->GetMacro().isEmpty() )
1382 // 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
1383 // SetMacroLink( XclControlHelper::GetXclMacroName( pInfo->GetMacro(), rRoot.GetDocShell() ) );
1384 SetMacroLink( XclTools::GetXclMacroName( pInfo->GetMacro() ) );
1388 XclExpShapeObj::~XclExpShapeObj()
1392 void XclExpShapeObj::WriteSubRecs( XclExpStream& rStrm )
1394 XclObjAny::WriteSubRecs( rStrm );
1395 WriteMacroSubRec( rStrm );
1398 XclExpComments::XclExpComments( SCTAB nTab, XclExpRecordList< XclExpNote >& rNotes )
1399 : mnTab( nTab ), mrNotes( rNotes )
1403 struct OUStringLess : public std::binary_function<OUString, OUString, bool>
1405 bool operator()(const OUString& x, const OUString& y) const
1407 return x.compareTo( y ) < 0;
1411 void XclExpComments::SaveXml( XclExpXmlStream& rStrm )
1413 if( mrNotes.IsEmpty() )
1414 return;
1416 sax_fastparser::FSHelperPtr rComments = rStrm.CreateOutputStream(
1417 XclXmlUtils::GetStreamName( "xl/", "comments", mnTab + 1 ),
1418 XclXmlUtils::GetStreamName( "../", "comments", mnTab + 1 ),
1419 rStrm.GetCurrentStream()->getOutputStream(),
1420 "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml",
1421 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments" );
1422 rStrm.PushStream( rComments );
1424 if( rStrm.getVersion() == oox::core::ISOIEC_29500_2008 )
1425 rComments->startElement( XML_comments,
1426 XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
1427 FSNS( XML_xmlns, XML_mc ), "http://schemas.openxmlformats.org/markup-compatibility/2006",
1428 FSNS( XML_xmlns, XML_xdr ), "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing",
1429 FSNS( XML_xmlns, XML_v2 ), "http://schemas.openxmlformats.org/spreadsheetml/2006/main/v2",
1430 FSNS( XML_mc, XML_Ignorable ), "v2",
1431 FSEND );
1432 else
1433 rComments->startElement( XML_comments,
1434 XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
1435 FSNS( XML_xmlns, XML_xdr ), "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing",
1436 FSEND );
1438 rComments->startElement( XML_authors, FSEND );
1440 typedef std::set< OUString, OUStringLess > Authors;
1441 Authors aAuthors;
1443 size_t nNotes = mrNotes.GetSize();
1444 for( size_t i = 0; i < nNotes; ++i )
1446 aAuthors.insert( XclXmlUtils::ToOUString( mrNotes.GetRecord( i )->GetAuthor() ) );
1449 for( Authors::const_iterator b = aAuthors.begin(), e = aAuthors.end(); b != e; ++b )
1451 rComments->startElement( XML_author, FSEND );
1452 rComments->writeEscaped( *b );
1453 rComments->endElement( XML_author );
1456 rComments->endElement( XML_authors );
1457 rComments->startElement( XML_commentList, FSEND );
1459 Authors::const_iterator aAuthorsBegin = aAuthors.begin();
1460 for( size_t i = 0; i < nNotes; ++i )
1462 XclExpNoteList::RecordRefType xNote = mrNotes.GetRecord( i );
1463 Authors::const_iterator aAuthor = aAuthors.find(
1464 XclXmlUtils::ToOUString( xNote->GetAuthor() ) );
1465 sal_Int32 nAuthorId = distance( aAuthorsBegin, aAuthor );
1466 xNote->WriteXml( nAuthorId, rStrm );
1469 rComments->endElement( XML_commentList );
1470 rComments->endElement( XML_comments );
1472 rStrm.PopStream();
1475 // object manager =============================================================
1477 XclExpObjectManager::XclExpObjectManager( const XclExpRoot& rRoot ) :
1478 XclExpRoot( rRoot )
1480 InitStream( true );
1481 mxEscherEx.reset( new XclEscherEx( GetRoot(), *this, *mxDffStrm ) );
1484 XclExpObjectManager::XclExpObjectManager( const XclExpObjectManager& rParent ) :
1485 XclExpRoot( rParent.GetRoot() )
1487 InitStream( false );
1488 mxEscherEx.reset( new XclEscherEx( GetRoot(), *this, *mxDffStrm, rParent.mxEscherEx.get() ) );
1491 XclExpObjectManager::~XclExpObjectManager()
1495 XclExpDffAnchorBase* XclExpObjectManager::CreateDffAnchor() const
1497 return new XclExpDffSheetAnchor( GetRoot() );
1500 std::shared_ptr< XclExpRecordBase > XclExpObjectManager::CreateDrawingGroup()
1502 return std::shared_ptr< XclExpRecordBase >( new XclExpMsoDrawingGroup( *mxEscherEx ) );
1505 void XclExpObjectManager::StartSheet()
1507 mxObjList.reset( new XclExpObjList( GetRoot(), *mxEscherEx ) );
1510 std::shared_ptr< XclExpRecordBase > XclExpObjectManager::ProcessDrawing( SdrPage* pSdrPage )
1512 if( pSdrPage )
1513 mxEscherEx->AddSdrPage( *pSdrPage );
1514 // the first dummy object may still be open
1515 OSL_ENSURE( mxEscherEx->GetGroupLevel() <= 1, "XclExpObjectManager::ProcessDrawing - still groups open?" );
1516 while( mxEscherEx->GetGroupLevel() )
1517 mxEscherEx->LeaveGroup();
1518 mxObjList->EndSheet();
1519 return mxObjList;
1522 std::shared_ptr< XclExpRecordBase > XclExpObjectManager::ProcessDrawing( const Reference< XShapes >& rxShapes )
1524 if( rxShapes.is() )
1525 mxEscherEx->AddUnoShapes( rxShapes );
1526 // the first dummy object may still be open
1527 OSL_ENSURE( mxEscherEx->GetGroupLevel() <= 1, "XclExpObjectManager::ProcessDrawing - still groups open?" );
1528 while( mxEscherEx->GetGroupLevel() )
1529 mxEscherEx->LeaveGroup();
1530 mxObjList->EndSheet();
1531 return mxObjList;
1534 void XclExpObjectManager::EndDocument()
1536 mxEscherEx->EndDocument();
1539 XclExpMsoDrawing* XclExpObjectManager::GetMsodrawingPerSheet()
1541 return mxObjList->GetMsodrawingPerSheet();
1544 bool XclExpObjectManager::HasObj() const
1546 return !mxObjList->empty();
1549 sal_uInt16 XclExpObjectManager::AddObj( XclObj* pObjRec )
1551 return mxObjList->Add( pObjRec );
1554 XclObj* XclExpObjectManager::RemoveLastObj()
1556 XclObj* pLastObj = mxObjList->back();
1557 mxObjList->pop_back();
1558 return pLastObj;
1561 void XclExpObjectManager::InitStream( bool bTempFile )
1563 if( bTempFile )
1565 mxTempFile.reset( new ::utl::TempFile );
1566 if( mxTempFile->IsValid() )
1568 mxTempFile->EnableKillingFile();
1569 mxDffStrm.reset( ::utl::UcbStreamHelper::CreateStream( mxTempFile->GetURL(), STREAM_STD_READWRITE ) );
1573 if( !mxDffStrm.get() )
1574 mxDffStrm.reset( new SvMemoryStream );
1576 mxDffStrm->SetEndian( SvStreamEndian::LITTLE );
1579 XclExpEmbeddedObjectManager::XclExpEmbeddedObjectManager(
1580 const XclExpObjectManager& rParent, const Size& rPageSize, sal_Int32 nScaleX, sal_Int32 nScaleY ) :
1581 XclExpObjectManager( rParent ),
1582 maPageSize( rPageSize ),
1583 mnScaleX( nScaleX ),
1584 mnScaleY( nScaleY )
1588 XclExpDffAnchorBase* XclExpEmbeddedObjectManager::CreateDffAnchor() const
1590 return new XclExpDffEmbeddedAnchor( GetRoot(), maPageSize, mnScaleX, mnScaleY );
1593 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */