1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <xeescher.hxx>
21
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/awt/Size.hpp>
31 #include <com/sun/star/chart/XChartDocument.hpp>
32
33 #include <set>
34 #include <vcl/bitmapaccess.hxx>
35 #include <svx/svdoole2.hxx>
36 #include <svx/svdocapt.hxx>
37 #include <editeng/outlobj.hxx>
38 #include <unotools/tempfile.hxx>
39 #include <unotools/ucbstreamhelper.hxx>
40 #include <svtools/embedhlp.hxx>
41
42 #include <unonames.hxx>
43 #include <convuno.hxx>
44 #include <postit.hxx>
45
46 #include <fapihelper.hxx>
47 #include <xcl97esc.hxx>
48 #include <xechart.hxx>
49 #include <xeformula.hxx>
50 #include <xehelper.hxx>
51 #include <xelink.hxx>
52 #include <xename.hxx>
53 #include <xestyle.hxx>
54 #include <xllink.hxx>
55 #include <xltools.hxx>
56 #include <userdat.hxx>
57 #include <drwlayer.hxx>
58 #include <svl/itemset.hxx>
59 #include <svx/unoapi.hxx>
60 #include <svx/sdtaitm.hxx>
61 #include <document.hxx>
62 #include <svx/xfillit0.hxx>
63 #include <svx/xflclit.hxx>
64
65 #include <comphelper/sequence.hxx>
66 #include <oox/token/tokens.hxx>
67 #include <oox/token/relationship.hxx>
68 #include <oox/export/drawingml.hxx>
69 #include <oox/export/chartexport.hxx>
70 #include <oox/export/utils.hxx>
71 #include <oox/token/namespaces.hxx>
72 #include <memory>
73
74 using namespace com::sun::star;
75 using ::com::sun::star::uno::UNO_QUERY;
76 using ::com::sun::star::uno::Reference;
77 using ::com::sun::star::uno::Sequence;
78 using ::com::sun::star::lang::XServiceInfo;
79 using ::com::sun::star::beans::XPropertySet;
80 using ::com::sun::star::drawing::XShape;
81 using ::com::sun::star::drawing::XShapes;
82 using ::com::sun::star::frame::XModel;
83 using ::com::sun::star::awt::XControlModel;
84 using ::com::sun::star::form::binding::XBindableValue;
85 using ::com::sun::star::form::binding::XListEntrySink;
86 using ::com::sun::star::script::ScriptEventDescriptor;
87 using ::com::sun::star::table::CellAddress;
88 using ::com::sun::star::table::CellRangeAddress;
89 using ::oox::drawingml::DrawingML;
90 using ::oox::drawingml::ChartExport;
91 using namespace oox;
92
93 namespace
94 {
95
lcl_hmm2px(long nPixel)96 long lcl_hmm2px(long nPixel)
97 {
98 return static_cast<long>(nPixel*PIXEL_PER_INCH/1000.0/CM_PER_INCH + 0.5);
99 }
100
ToHorizAlign(SdrTextHorzAdjust eAdjust)101 const char *ToHorizAlign( SdrTextHorzAdjust eAdjust )
102 {
103 switch( eAdjust )
104 {
105 case SDRTEXTHORZADJUST_CENTER:
106 return "center";
107 case SDRTEXTHORZADJUST_RIGHT:
108 return "right";
109 case SDRTEXTHORZADJUST_BLOCK:
110 return "justify";
111 case SDRTEXTHORZADJUST_LEFT:
112 default:
113 return "left";
114 }
115 }
116
ToVertAlign(SdrTextVertAdjust eAdjust)117 const char *ToVertAlign( SdrTextVertAdjust eAdjust )
118 {
119 switch( eAdjust )
120 {
121 case SDRTEXTVERTADJUST_CENTER:
122 return "center";
123 case SDRTEXTVERTADJUST_BOTTOM:
124 return "bottom";
125 case SDRTEXTVERTADJUST_BLOCK:
126 return "justify";
127 case SDRTEXTVERTADJUST_TOP:
128 default:
129 return "top";
130 }
131 }
132
lcl_WriteAnchorVertex(sax_fastparser::FSHelperPtr const & rComments,const tools::Rectangle & aRect)133 void lcl_WriteAnchorVertex( sax_fastparser::FSHelperPtr const & rComments, const tools::Rectangle &aRect )
134 {
135 rComments->startElement(FSNS(XML_xdr, XML_col));
136 rComments->writeEscaped( OUString::number( aRect.Left() ) );
137 rComments->endElement( FSNS( XML_xdr, XML_col ) );
138 rComments->startElement(FSNS(XML_xdr, XML_colOff));
139 rComments->writeEscaped( OUString::number( aRect.Top() ) );
140 rComments->endElement( FSNS( XML_xdr, XML_colOff ) );
141 rComments->startElement(FSNS(XML_xdr, XML_row));
142 rComments->writeEscaped( OUString::number( aRect.Right() ) );
143 rComments->endElement( FSNS( XML_xdr, XML_row ) );
144 rComments->startElement(FSNS(XML_xdr, XML_rowOff));
145 rComments->writeEscaped( OUString::number( aRect.Bottom() ) );
146 rComments->endElement( FSNS( XML_xdr, XML_rowOff ) );
147 }
148
lcl_hmm2output(long value,bool bInEMU)149 long lcl_hmm2output(long value, bool bInEMU)
150 {
151 if (bInEMU)
152 return oox::drawingml::convertHmmToEmu(value);
153 else
154 return lcl_hmm2px(value);
155 }
156
lcl_GetFromTo(const XclExpRoot & rRoot,const tools::Rectangle & aRect,sal_Int32 nTab,tools::Rectangle & aFrom,tools::Rectangle & aTo,bool bInEMU=false)157 void lcl_GetFromTo( const XclExpRoot& rRoot, const tools::Rectangle &aRect, sal_Int32 nTab, tools::Rectangle &aFrom, tools::Rectangle &aTo, bool bInEMU = false )
158 {
159 sal_Int32 nCol = 0, nRow = 0;
160 sal_Int32 nColOff = 0, nRowOff= 0;
161
162 const bool bRTL = rRoot.GetDoc().IsNegativePage( nTab );
163 if (!bRTL)
164 {
165 while(true)
166 {
167 tools::Rectangle r = rRoot.GetDoc().GetMMRect( nCol,nRow,nCol,nRow,nTab );
168 if( r.Left() <= aRect.Left() )
169 {
170 nCol++;
171 nColOff = aRect.Left() - r.Left();
172 }
173 if( r.Top() <= aRect.Top() )
174 {
175 nRow++;
176 nRowOff = aRect.Top() - r.Top();
177 }
178 if( r.Left() > aRect.Left() && r.Top() > aRect.Top() )
179 {
180 aFrom = tools::Rectangle( nCol-1, lcl_hmm2output( nColOff, bInEMU ),
181 nRow-1, lcl_hmm2output( nRowOff, bInEMU ) );
182 break;
183 }
184 }
185 }
186 else
187 {
188 while(true)
189 {
190 tools::Rectangle r = rRoot.GetDoc().GetMMRect( nCol,nRow,nCol,nRow,nTab );
191 if( r.Left() >= aRect.Left() )
192 {
193 nCol++;
194 nColOff = r.Left() - aRect.Left();
195 }
196 if( r.Top() <= aRect.Top() )
197 {
198 nRow++;
199 nRowOff = aRect.Top() - r.Top();
200 }
201 if( r.Left() < aRect.Left() && r.Top() > aRect.Top() )
202 {
203 aFrom = tools::Rectangle( nCol-1, lcl_hmm2output( nColOff, bInEMU ),
204 nRow-1, lcl_hmm2output( nRowOff, bInEMU ) );
205 break;
206 }
207 }
208 }
209 if (!bRTL)
210 {
211 while(true)
212 {
213 tools::Rectangle r = rRoot.GetDoc().GetMMRect( nCol,nRow,nCol,nRow,nTab );
214 if( r.Right() < aRect.Right() )
215 nCol++;
216 if( r.Bottom() < aRect.Bottom() )
217 nRow++;
218 if( r.Right() >= aRect.Right() && r.Bottom() >= aRect.Bottom() )
219 {
220 aTo = tools::Rectangle( nCol, lcl_hmm2output( aRect.Right() - r.Left(), bInEMU ),
221 nRow, lcl_hmm2output( aRect.Bottom() - r.Top(), bInEMU ));
222 break;
223 }
224 }
225 }
226 else
227 {
228 while(true)
229 {
230 tools::Rectangle r = rRoot.GetDoc().GetMMRect( nCol,nRow,nCol,nRow,nTab );
231 if( r.Right() >= aRect.Right() )
232 nCol++;
233 if( r.Bottom() < aRect.Bottom() )
234 nRow++;
235 if( r.Right() < aRect.Right() && r.Bottom() >= aRect.Bottom() )
236 {
237 aTo = tools::Rectangle( nCol, lcl_hmm2output( r.Left() - aRect.Right(), bInEMU ),
238 nRow, lcl_hmm2output( aRect.Bottom() - r.Top(), bInEMU ));
239 break;
240 }
241 }
242 }
243 }
244
245 } // namespace
246
247 // Escher client anchor =======================================================
248
XclExpDffAnchorBase(const XclExpRoot & rRoot,sal_uInt16 nFlags)249 XclExpDffAnchorBase::XclExpDffAnchorBase( const XclExpRoot& rRoot, sal_uInt16 nFlags ) :
250 XclExpRoot( rRoot ),
251 mnFlags( nFlags )
252 {
253 }
254
SetFlags(const SdrObject & rSdrObj)255 void XclExpDffAnchorBase::SetFlags( const SdrObject& rSdrObj )
256 {
257 ImplSetFlags( rSdrObj );
258 }
259
SetSdrObject(const SdrObject & rSdrObj)260 void XclExpDffAnchorBase::SetSdrObject( const SdrObject& rSdrObj )
261 {
262 ImplSetFlags( rSdrObj );
263 ImplCalcAnchorRect( rSdrObj.GetCurrentBoundRect(), MapUnit::Map100thMM );
264 }
265
WriteDffData(EscherEx & rEscherEx) const266 void XclExpDffAnchorBase::WriteDffData( EscherEx& rEscherEx ) const
267 {
268 rEscherEx.AddAtom( 18, ESCHER_ClientAnchor );
269 rEscherEx.GetStream().WriteUInt16( mnFlags );
270 WriteXclObjAnchor( rEscherEx.GetStream(), maAnchor );
271 }
272
WriteData(EscherEx & rEscherEx,const tools::Rectangle & rRect)273 void XclExpDffAnchorBase::WriteData( EscherEx& rEscherEx, const tools::Rectangle& rRect )
274 {
275 // the passed rectangle is in twips
276 ImplCalcAnchorRect( rRect, MapUnit::MapTwip );
277 WriteDffData( rEscherEx );
278 }
279
ImplSetFlags(const SdrObject &)280 void XclExpDffAnchorBase::ImplSetFlags( const SdrObject& )
281 {
282 OSL_FAIL( "XclExpDffAnchorBase::ImplSetFlags - not implemented" );
283 }
284
ImplCalcAnchorRect(const tools::Rectangle &,MapUnit)285 void XclExpDffAnchorBase::ImplCalcAnchorRect( const tools::Rectangle&, MapUnit )
286 {
287 OSL_FAIL( "XclExpDffAnchorBase::ImplCalcAnchorRect - not implemented" );
288 }
289
XclExpDffSheetAnchor(const XclExpRoot & rRoot)290 XclExpDffSheetAnchor::XclExpDffSheetAnchor( const XclExpRoot& rRoot ) :
291 XclExpDffAnchorBase( rRoot ),
292 mnScTab( rRoot.GetCurrScTab() )
293 {
294 }
295
ImplSetFlags(const SdrObject & rSdrObj)296 void XclExpDffSheetAnchor::ImplSetFlags( const SdrObject& rSdrObj )
297 {
298 // set flags for cell/page anchoring
299 if ( ScDrawLayer::GetAnchorType( rSdrObj ) == SCA_CELL )
300 mnFlags = 0;
301 else
302 mnFlags = EXC_ESC_ANCHOR_LOCKED;
303 }
304
ImplCalcAnchorRect(const tools::Rectangle & rRect,MapUnit eMapUnit)305 void XclExpDffSheetAnchor::ImplCalcAnchorRect( const tools::Rectangle& rRect, MapUnit eMapUnit )
306 {
307 maAnchor.SetRect( GetRoot(), mnScTab, rRect, eMapUnit );
308 }
309
XclExpDffEmbeddedAnchor(const XclExpRoot & rRoot,const Size & rPageSize,sal_Int32 nScaleX,sal_Int32 nScaleY)310 XclExpDffEmbeddedAnchor::XclExpDffEmbeddedAnchor( const XclExpRoot& rRoot,
311 const Size& rPageSize, sal_Int32 nScaleX, sal_Int32 nScaleY ) :
312 XclExpDffAnchorBase( rRoot ),
313 maPageSize( rPageSize ),
314 mnScaleX( nScaleX ),
315 mnScaleY( nScaleY )
316 {
317 }
318
ImplSetFlags(const SdrObject &)319 void XclExpDffEmbeddedAnchor::ImplSetFlags( const SdrObject& /*rSdrObj*/ )
320 {
321 // TODO (unsupported feature): fixed size
322 }
323
ImplCalcAnchorRect(const tools::Rectangle & rRect,MapUnit eMapUnit)324 void XclExpDffEmbeddedAnchor::ImplCalcAnchorRect( const tools::Rectangle& rRect, MapUnit eMapUnit )
325 {
326 maAnchor.SetRect( maPageSize, mnScaleX, mnScaleY, rRect, eMapUnit );
327 }
328
XclExpDffNoteAnchor(const XclExpRoot & rRoot,const tools::Rectangle & rRect)329 XclExpDffNoteAnchor::XclExpDffNoteAnchor( const XclExpRoot& rRoot, const tools::Rectangle& rRect ) :
330 XclExpDffAnchorBase( rRoot, EXC_ESC_ANCHOR_SIZELOCKED )
331 {
332 maAnchor.SetRect( rRoot, rRoot.GetCurrScTab(), rRect, MapUnit::Map100thMM );
333 }
334
XclExpDffDropDownAnchor(const XclExpRoot & rRoot,const ScAddress & rScPos)335 XclExpDffDropDownAnchor::XclExpDffDropDownAnchor( const XclExpRoot& rRoot, const ScAddress& rScPos ) :
336 XclExpDffAnchorBase( rRoot, EXC_ESC_ANCHOR_POSLOCKED )
337 {
338 GetAddressConverter().ConvertAddress( maAnchor.maFirst, rScPos, true );
339 maAnchor.maLast.mnCol = maAnchor.maFirst.mnCol + 1;
340 maAnchor.maLast.mnRow = maAnchor.maFirst.mnRow + 1;
341 maAnchor.mnLX = maAnchor.mnTY = maAnchor.mnRX = maAnchor.mnBY = 0;
342 }
343
344 // MSODRAWING* records ========================================================
345
XclExpMsoDrawingBase(XclEscherEx & rEscherEx,sal_uInt16 nRecId)346 XclExpMsoDrawingBase::XclExpMsoDrawingBase( XclEscherEx& rEscherEx, sal_uInt16 nRecId ) :
347 XclExpRecord( nRecId ),
348 mrEscherEx( rEscherEx ),
349 mnFragmentKey( rEscherEx.InitNextDffFragment() )
350 {
351 }
352
WriteBody(XclExpStream & rStrm)353 void XclExpMsoDrawingBase::WriteBody( XclExpStream& rStrm )
354 {
355 OSL_ENSURE( mrEscherEx.GetStreamPos() == mrEscherEx.GetDffFragmentPos( mnFragmentKey ),
356 "XclExpMsoDrawingBase::WriteBody - DFF stream position mismatch" );
357 rStrm.CopyFromStream( mrEscherEx.GetStream(), mrEscherEx.GetDffFragmentSize( mnFragmentKey ) );
358 }
359
XclExpMsoDrawingGroup(XclEscherEx & rEscherEx)360 XclExpMsoDrawingGroup::XclExpMsoDrawingGroup( XclEscherEx& rEscherEx ) :
361 XclExpMsoDrawingBase( rEscherEx, EXC_ID_MSODRAWINGGROUP )
362 {
363 SvStream& rDffStrm = mrEscherEx.GetStream();
364
365 // write the DGGCONTAINER with some default settings
366 mrEscherEx.OpenContainer( ESCHER_DggContainer );
367
368 // TODO: stuff the OPT atom with our own document defaults?
369 static const sal_uInt8 spnDffOpt[] = {
370 0xBF, 0x00, 0x08, 0x00, 0x08, 0x00, 0x81, 0x01,
371 0x09, 0x00, 0x00, 0x08, 0xC0, 0x01, 0x40, 0x00,
372 0x00, 0x08
373 };
374 mrEscherEx.AddAtom( sizeof( spnDffOpt ), ESCHER_OPT, 3, 3 );
375 rDffStrm.WriteBytes(spnDffOpt, sizeof(spnDffOpt));
376
377 // SPLITMENUCOLORS contains colors in toolbar
378 static const sal_uInt8 spnDffSplitMenuColors[] = {
379 0x0D, 0x00, 0x00, 0x08, 0x0C, 0x00, 0x00, 0x08,
380 0x17, 0x00, 0x00, 0x08, 0xF7, 0x00, 0x00, 0x10
381 };
382 mrEscherEx.AddAtom( sizeof( spnDffSplitMenuColors ), ESCHER_SplitMenuColors, 0, 4 );
383 rDffStrm.WriteBytes(spnDffSplitMenuColors, sizeof(spnDffSplitMenuColors));
384
385 // close the DGGCONTAINER
386 mrEscherEx.CloseContainer();
387 mrEscherEx.UpdateDffFragmentEnd();
388 }
389
XclExpMsoDrawing(XclEscherEx & rEscherEx)390 XclExpMsoDrawing::XclExpMsoDrawing( XclEscherEx& rEscherEx ) :
391 XclExpMsoDrawingBase( rEscherEx, EXC_ID_MSODRAWING )
392 {
393 }
394
XclExpImgData(const Graphic & rGraphic,sal_uInt16 nRecId)395 XclExpImgData::XclExpImgData( const Graphic& rGraphic, sal_uInt16 nRecId ) :
396 maGraphic( rGraphic ),
397 mnRecId( nRecId )
398 {
399 }
400
Save(XclExpStream & rStrm)401 void XclExpImgData::Save( XclExpStream& rStrm )
402 {
403 Bitmap aBmp = maGraphic.GetBitmapEx().GetBitmap();
404 if( aBmp.GetBitCount() != 24 )
405 aBmp.Convert( BmpConversion::N24Bit );
406
407 Bitmap::ScopedReadAccess pAccess(aBmp);
408 if( pAccess )
409 {
410 sal_Int32 nWidth = ::std::min< sal_Int32 >( pAccess->Width(), 0xFFFF );
411 sal_Int32 nHeight = ::std::min< sal_Int32 >( pAccess->Height(), 0xFFFF );
412 if( (nWidth > 0) && (nHeight > 0) )
413 {
414 sal_uInt8 nPadding = static_cast< sal_uInt8 >( nWidth & 0x03 );
415 sal_uInt32 nTmpSize = static_cast< sal_uInt32 >( (nWidth * 3 + nPadding) * nHeight + 12 );
416
417 rStrm.StartRecord( mnRecId, nTmpSize + 4 );
418
419 rStrm << EXC_IMGDATA_BMP // BMP format
420 << EXC_IMGDATA_WIN // Windows
421 << nTmpSize // size after _this_ field
422 << sal_uInt32( 12 ) // BITMAPCOREHEADER size
423 << static_cast< sal_uInt16 >( nWidth ) // width
424 << static_cast< sal_uInt16 >( nHeight ) // height
425 << sal_uInt16( 1 ) // planes
426 << sal_uInt16( 24 ); // bits per pixel
427
428 for( sal_Int32 nY = nHeight - 1; nY >= 0; --nY )
429 {
430 Scanline pScanline = pAccess->GetScanline( nY );
431 for( sal_Int32 nX = 0; nX < nWidth; ++nX )
432 {
433 const BitmapColor& rBmpColor = pAccess->GetPixelFromData( pScanline, nX );
434 rStrm << rBmpColor.GetBlue() << rBmpColor.GetGreen() << rBmpColor.GetRed();
435 }
436 rStrm.WriteZeroBytes( nPadding );
437 }
438
439 rStrm.EndRecord();
440 }
441 }
442 }
443
SaveXml(XclExpXmlStream & rStrm)444 void XclExpImgData::SaveXml( XclExpXmlStream& rStrm )
445 {
446 sax_fastparser::FSHelperPtr pWorksheet = rStrm.GetCurrentStream();
447
448 DrawingML aDML(pWorksheet, &rStrm, drawingml::DOCUMENT_XLSX);
449 OUString rId = aDML.WriteImage( maGraphic );
450 pWorksheet->singleElement(XML_picture, FSNS(XML_r, XML_id), rId.toUtf8());
451 }
452
XclExpControlHelper(const XclExpRoot & rRoot)453 XclExpControlHelper::XclExpControlHelper( const XclExpRoot& rRoot ) :
454 XclExpRoot( rRoot ),
455 mnEntryCount( 0 )
456 {
457 }
458
~XclExpControlHelper()459 XclExpControlHelper::~XclExpControlHelper()
460 {
461 }
462
ConvertSheetLinks(Reference<XShape> const & xShape)463 void XclExpControlHelper::ConvertSheetLinks( Reference< XShape > const & xShape )
464 {
465 mxCellLink.reset();
466 mxCellLinkAddress.SetInvalid();
467 mxSrcRange.reset();
468 mnEntryCount = 0;
469
470 // get control model
471 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( xShape );
472 if( !xCtrlModel.is() )
473 return;
474
475 // *** cell link *** ------------------------------------------------------
476
477 Reference< XBindableValue > xBindable( xCtrlModel, UNO_QUERY );
478 if( xBindable.is() )
479 {
480 Reference< XServiceInfo > xServInfo( xBindable->getValueBinding(), UNO_QUERY );
481 if( xServInfo.is() && xServInfo->supportsService( SC_SERVICENAME_VALBIND ) )
482 {
483 ScfPropertySet aBindProp( xServInfo );
484 CellAddress aApiAddress;
485 if( aBindProp.GetProperty( aApiAddress, SC_UNONAME_BOUNDCELL ) )
486 {
487 ScUnoConversion::FillScAddress( mxCellLinkAddress, aApiAddress );
488 if( GetTabInfo().IsExportTab( mxCellLinkAddress.Tab() ) )
489 mxCellLink = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CONTROL, mxCellLinkAddress );
490 }
491 }
492 }
493
494 // *** source range *** ---------------------------------------------------
495
496 Reference< XListEntrySink > xEntrySink( xCtrlModel, UNO_QUERY );
497 if( xEntrySink.is() )
498 {
499 Reference< XServiceInfo > xServInfo( xEntrySink->getListEntrySource(), UNO_QUERY );
500 if( xServInfo.is() && xServInfo->supportsService( SC_SERVICENAME_LISTSOURCE ) )
501 {
502 ScfPropertySet aSinkProp( xServInfo );
503 CellRangeAddress aApiRange;
504 if( aSinkProp.GetProperty( aApiRange, SC_UNONAME_CELLRANGE ) )
505 {
506 ScRange aSrcRange;
507 ScUnoConversion::FillScRange( aSrcRange, aApiRange );
508 if( (aSrcRange.aStart.Tab() == aSrcRange.aEnd.Tab()) && GetTabInfo().IsExportTab( aSrcRange.aStart.Tab() ) )
509 mxSrcRange = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CONTROL, aSrcRange );
510 mnEntryCount = static_cast< sal_uInt16 >( aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1 );
511 }
512 }
513 }
514 }
515
WriteFormula(XclExpStream & rStrm,const XclTokenArray & rTokArr)516 void XclExpControlHelper::WriteFormula( XclExpStream& rStrm, const XclTokenArray& rTokArr )
517 {
518 sal_uInt16 nFmlaSize = rTokArr.GetSize();
519 rStrm << nFmlaSize << sal_uInt32( 0 );
520 rTokArr.WriteArray( rStrm );
521 if( nFmlaSize & 1 ) // pad to 16-bit
522 rStrm << sal_uInt8( 0 );
523 }
524
WriteFormulaSubRec(XclExpStream & rStrm,sal_uInt16 nSubRecId,const XclTokenArray & rTokArr)525 void XclExpControlHelper::WriteFormulaSubRec( XclExpStream& rStrm, sal_uInt16 nSubRecId, const XclTokenArray& rTokArr )
526 {
527 rStrm.StartRecord( nSubRecId, (rTokArr.GetSize() + 5) & ~1 );
528 WriteFormula( rStrm, rTokArr );
529 rStrm.EndRecord();
530 }
531
532 //delete for exporting OCX
533 //#if EXC_EXP_OCX_CTRL
534
XclExpOcxControlObj(XclExpObjectManager & rObjMgr,Reference<XShape> const & xShape,const tools::Rectangle * pChildAnchor,const OUString & rClassName,sal_uInt32 nStrmStart,sal_uInt32 nStrmSize)535 XclExpOcxControlObj::XclExpOcxControlObj( XclExpObjectManager& rObjMgr, Reference< XShape > const & xShape,
536 const tools::Rectangle* pChildAnchor, const OUString& rClassName, sal_uInt32 nStrmStart, sal_uInt32 nStrmSize ) :
537 XclObj( rObjMgr, EXC_OBJTYPE_PICTURE, true ),
538 XclExpControlHelper( rObjMgr.GetRoot() ),
539 maClassName( rClassName ),
540 mnStrmStart( nStrmStart ),
541 mnStrmSize( nStrmSize )
542 {
543 ScfPropertySet aCtrlProp( XclControlHelper::GetControlModel( xShape ) );
544
545 // OBJ record flags
546 SetLocked( true );
547 SetPrintable( aCtrlProp.GetBoolProperty( "Printable" ) );
548 SetAutoFill( false );
549 SetAutoLine( false );
550
551 // fill DFF property set
552 mrEscherEx.OpenContainer( ESCHER_SpContainer );
553 mrEscherEx.AddShape( ESCHER_ShpInst_HostControl,
554 ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor | ShapeFlag::OLEShape );
555 tools::Rectangle aDummyRect;
556 EscherPropertyContainer aPropOpt( mrEscherEx.GetGraphicProvider(), mrEscherEx.QueryPictureStream(), aDummyRect );
557 aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x00080008 ); // bool field
558 aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x08000040 );
559 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080000 ); // bool field
560
561 // #i51348# name of the control, may overwrite shape name
562 OUString aCtrlName;
563 if( aCtrlProp.GetProperty( aCtrlName, "Name" ) && !aCtrlName.isEmpty() )
564 aPropOpt.AddOpt( ESCHER_Prop_wzName, aCtrlName );
565
566 // meta file
567 //TODO - needs check
568 Reference< XPropertySet > xShapePS( xShape, UNO_QUERY );
569 if( xShapePS.is() && aPropOpt.CreateGraphicProperties( xShapePS, "MetaFile", false ) )
570 {
571 sal_uInt32 nBlipId;
572 if( aPropOpt.GetOpt( ESCHER_Prop_pib, nBlipId ) )
573 aPropOpt.AddOpt( ESCHER_Prop_pictureId, nBlipId );
574 }
575
576 // write DFF property set to stream
577 aPropOpt.Commit( mrEscherEx.GetStream() );
578
579 // anchor
580 ImplWriteAnchor( SdrObject::getSdrObjectFromXShape( xShape ), pChildAnchor );
581
582 mrEscherEx.AddAtom( 0, ESCHER_ClientData ); // OBJ record
583 mrEscherEx.CloseContainer(); // ESCHER_SpContainer
584 mrEscherEx.UpdateDffFragmentEnd();
585
586 // spreadsheet links
587 ConvertSheetLinks( xShape );
588 }
589
WriteSubRecs(XclExpStream & rStrm)590 void XclExpOcxControlObj::WriteSubRecs( XclExpStream& rStrm )
591 {
592 // OBJCF - clipboard format
593 rStrm.StartRecord( EXC_ID_OBJCF, 2 );
594 rStrm << sal_uInt16( 2 );
595 rStrm.EndRecord();
596
597 // OBJFLAGS
598 rStrm.StartRecord( EXC_ID_OBJFLAGS, 2 );
599 rStrm << sal_uInt16( 0x0031 );
600 rStrm.EndRecord();
601
602 // OBJPICTFMLA
603 XclExpString aClass( maClassName );
604 sal_uInt16 nClassNameSize = static_cast< sal_uInt16 >( aClass.GetSize() );
605 sal_uInt16 nClassNamePad = nClassNameSize & 1;
606 sal_uInt16 nFirstPartSize = 12 + nClassNameSize + nClassNamePad;
607
608 const XclTokenArray* pCellLink = GetCellLinkTokArr();
609 sal_uInt16 nCellLinkSize = pCellLink ? ((pCellLink->GetSize() + 7) & 0xFFFE) : 0;
610
611 const XclTokenArray* pSrcRange = GetSourceRangeTokArr();
612 sal_uInt16 nSrcRangeSize = pSrcRange ? ((pSrcRange->GetSize() + 7) & 0xFFFE) : 0;
613
614 sal_uInt16 nPictFmlaSize = nFirstPartSize + nCellLinkSize + nSrcRangeSize + 18;
615 rStrm.StartRecord( EXC_ID_OBJPICTFMLA, nPictFmlaSize );
616
617 rStrm << nFirstPartSize // size of first part
618 << sal_uInt16( 5 ) // formula size
619 << sal_uInt32( 0 ) // unknown ID
620 << sal_uInt8( 0x02 ) << sal_uInt32( 0 ) // tTbl token with unknown ID
621 << sal_uInt8( 3 ) // pad to word
622 << aClass; // "Forms.***.1"
623 rStrm.WriteZeroBytes( nClassNamePad ); // pad to word
624 rStrm << mnStrmStart // start in 'Ctls' stream
625 << mnStrmSize // size in 'Ctls' stream
626 << sal_uInt32( 0 ); // class ID size
627 // cell link
628 rStrm << nCellLinkSize;
629 if( pCellLink )
630 WriteFormula( rStrm, *pCellLink );
631 // list source range
632 rStrm << nSrcRangeSize;
633 if( pSrcRange )
634 WriteFormula( rStrm, *pSrcRange );
635
636 rStrm.EndRecord();
637 }
638
639 //#else
640
XclExpTbxControlObj(XclExpObjectManager & rRoot,Reference<XShape> const & xShape,const tools::Rectangle * pChildAnchor)641 XclExpTbxControlObj::XclExpTbxControlObj( XclExpObjectManager& rRoot, Reference< XShape > const & xShape , const tools::Rectangle* pChildAnchor ) :
642 XclObj( rRoot, EXC_OBJTYPE_UNKNOWN, true ),
643 XclMacroHelper( rRoot ),
644 mxShape( xShape ),
645 meEventType( EXC_TBX_EVENT_ACTION ),
646 mnHeight( 0 ),
647 mnState( 0 ),
648 mnLineCount( 0 ),
649 mnSelEntry( 0 ),
650 mnScrollValue( 0 ),
651 mnScrollMin( 0 ),
652 mnScrollMax( 100 ),
653 mnScrollStep( 1 ),
654 mnScrollPage( 10 ),
655 mbFlatButton( false ),
656 mbFlatBorder( false ),
657 mbMultiSel( false ),
658 mbScrollHor( false ),
659 mbPrint( false ),
660 mbVisible( false ),
661 mnShapeId( 0 )
662 {
663 namespace FormCompType = css::form::FormComponentType;
664 namespace AwtVisualEffect = css::awt::VisualEffect;
665 namespace AwtScrollOrient = css::awt::ScrollBarOrientation;
666
667 ScfPropertySet aCtrlProp( XclControlHelper::GetControlModel( xShape ) );
668 if( !xShape.is() || !aCtrlProp.Is() )
669 return;
670
671 mnHeight = xShape->getSize().Height;
672 if( mnHeight <= 0 )
673 return;
674
675 // control type
676 sal_Int16 nClassId = 0;
677 if( aCtrlProp.GetProperty( nClassId, "ClassId" ) )
678 {
679 switch( nClassId )
680 {
681 case FormCompType::COMMANDBUTTON: mnObjType = EXC_OBJTYPE_BUTTON; meEventType = EXC_TBX_EVENT_ACTION; break;
682 case FormCompType::RADIOBUTTON: mnObjType = EXC_OBJTYPE_OPTIONBUTTON; meEventType = EXC_TBX_EVENT_ACTION; break;
683 case FormCompType::CHECKBOX: mnObjType = EXC_OBJTYPE_CHECKBOX; meEventType = EXC_TBX_EVENT_ACTION; break;
684 case FormCompType::LISTBOX: mnObjType = EXC_OBJTYPE_LISTBOX; meEventType = EXC_TBX_EVENT_CHANGE; break;
685 case FormCompType::COMBOBOX: mnObjType = EXC_OBJTYPE_DROPDOWN; meEventType = EXC_TBX_EVENT_CHANGE; break;
686 case FormCompType::GROUPBOX: mnObjType = EXC_OBJTYPE_GROUPBOX; meEventType = EXC_TBX_EVENT_MOUSE; break;
687 case FormCompType::FIXEDTEXT: mnObjType = EXC_OBJTYPE_LABEL; meEventType = EXC_TBX_EVENT_MOUSE; break;
688 case FormCompType::SCROLLBAR: mnObjType = EXC_OBJTYPE_SCROLLBAR; meEventType = EXC_TBX_EVENT_VALUE; break;
689 case FormCompType::SPINBUTTON: mnObjType = EXC_OBJTYPE_SPIN; meEventType = EXC_TBX_EVENT_VALUE; break;
690 }
691 }
692 if( mnObjType == EXC_OBJTYPE_UNKNOWN )
693 return;
694
695 // OBJ record flags
696 SetLocked( true );
697 mbPrint = aCtrlProp.GetBoolProperty( "Printable" );
698 SetPrintable( mbPrint );
699 SetAutoFill( false );
700 SetAutoLine( false );
701
702 // fill DFF property set
703 mrEscherEx.OpenContainer( ESCHER_SpContainer );
704 mrEscherEx.AddShape( ESCHER_ShpInst_HostControl, ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty );
705 EscherPropertyContainer aPropOpt;
706 mbVisible = aCtrlProp.GetBoolProperty( "EnableVisible" );
707 aPropOpt.AddOpt( ESCHER_Prop_fPrint, mbVisible ? 0x00080000 : 0x00080002 ); // visible flag
708
709 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x01000100 ); // bool field
710 aPropOpt.AddOpt( ESCHER_Prop_lTxid, 0 ); // Text ID
711 aPropOpt.AddOpt( ESCHER_Prop_WrapText, 0x00000001 );
712 aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x001A0008 ); // bool field
713 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x00100000 ); // bool field
714 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080000 ); // bool field
715
716 // #i51348# name of the control, may overwrite shape name
717 if( aCtrlProp.GetProperty( msCtrlName, "Name" ) && !msCtrlName.isEmpty() )
718 aPropOpt.AddOpt( ESCHER_Prop_wzName, msCtrlName );
719
720 //Export description as alt text
721 if( SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape( xShape ) )
722 {
723 OUString aAltTxt;
724 OUString aDescrText = pSdrObj->GetDescription();
725 if(!aDescrText.isEmpty())
726 aAltTxt = aDescrText.copy( 0, std::min<sal_Int32>(MSPROP_DESCRIPTION_MAX_LEN, aDescrText.getLength()) );
727 aPropOpt.AddOpt( ESCHER_Prop_wzDescription, aAltTxt );
728 }
729
730 // write DFF property set to stream
731 aPropOpt.Commit( mrEscherEx.GetStream() );
732
733 // anchor
734 ImplWriteAnchor( SdrObject::getSdrObjectFromXShape( xShape ), pChildAnchor );
735
736 mrEscherEx.AddAtom( 0, ESCHER_ClientData ); // OBJ record
737 mrEscherEx.UpdateDffFragmentEnd();
738
739 // control label
740 if( aCtrlProp.GetProperty( msLabel, "Label" ) )
741 {
742 /* Be sure to construct the MSODRAWING record containing the
743 ClientTextbox atom after the base OBJ's MSODRAWING record data is
744 completed. */
745 pClientTextbox.reset( new XclExpMsoDrawing( mrEscherEx ) );
746 mrEscherEx.AddAtom( 0, ESCHER_ClientTextbox ); // TXO record
747 mrEscherEx.UpdateDffFragmentEnd();
748
749 sal_uInt16 nXclFont = EXC_FONT_APP;
750 if( !msLabel.isEmpty() )
751 {
752 XclFontData aFontData;
753 GetFontPropSetHelper().ReadFontProperties( aFontData, aCtrlProp, EXC_FONTPROPSET_CONTROL );
754 if( (!aFontData.maName.isEmpty() ) && (aFontData.mnHeight > 0) )
755 nXclFont = GetFontBuffer().Insert( aFontData, EXC_COLOR_CTRLTEXT );
756 }
757
758 pTxo.reset( new XclTxo( msLabel, nXclFont ) );
759 pTxo->SetHorAlign( (mnObjType == EXC_OBJTYPE_BUTTON) ? EXC_OBJ_HOR_CENTER : EXC_OBJ_HOR_LEFT );
760 pTxo->SetVerAlign( EXC_OBJ_VER_CENTER );
761 }
762
763 mrEscherEx.CloseContainer(); // ESCHER_SpContainer
764
765 // other properties
766 aCtrlProp.GetProperty( mnLineCount, "LineCount" );
767
768 // border style
769 sal_Int16 nApiButton = AwtVisualEffect::LOOK3D;
770 sal_Int16 nApiBorder = AwtVisualEffect::LOOK3D;
771 switch( nClassId )
772 {
773 case FormCompType::LISTBOX:
774 case FormCompType::COMBOBOX:
775 aCtrlProp.GetProperty( nApiBorder, "Border" );
776 break;
777 case FormCompType::CHECKBOX:
778 case FormCompType::RADIOBUTTON:
779 aCtrlProp.GetProperty( nApiButton, "VisualEffect" );
780 nApiBorder = AwtVisualEffect::NONE;
781 break;
782 // Push button cannot be set to flat in Excel
783 case FormCompType::COMMANDBUTTON:
784 nApiBorder = AwtVisualEffect::LOOK3D;
785 break;
786 // Label does not support a border in Excel
787 case FormCompType::FIXEDTEXT:
788 nApiBorder = AwtVisualEffect::NONE;
789 break;
790 /* Scroll bar and spin button have a "Border" property, but it is
791 really used for a border, and not for own 3D/flat look (#i34712#). */
792 case FormCompType::SCROLLBAR:
793 case FormCompType::SPINBUTTON:
794 nApiButton = AwtVisualEffect::LOOK3D;
795 nApiBorder = AwtVisualEffect::NONE;
796 break;
797 // Group box does not support flat style (#i34712#)
798 case FormCompType::GROUPBOX:
799 nApiBorder = AwtVisualEffect::LOOK3D;
800 break;
801 }
802 mbFlatButton = nApiButton != AwtVisualEffect::LOOK3D;
803 mbFlatBorder = nApiBorder != AwtVisualEffect::LOOK3D;
804
805 // control state
806 sal_Int16 nApiState = 0;
807 if( aCtrlProp.GetProperty( nApiState, "State" ) )
808 {
809 switch( nApiState )
810 {
811 case 0: mnState = EXC_OBJ_CHECKBOX_UNCHECKED; break;
812 case 1: mnState = EXC_OBJ_CHECKBOX_CHECKED; break;
813 case 2: mnState = EXC_OBJ_CHECKBOX_TRISTATE; break;
814 }
815 }
816
817 // special control contents
818 switch( nClassId )
819 {
820 case FormCompType::LISTBOX:
821 {
822 mbMultiSel = aCtrlProp.GetBoolProperty( "MultiSelection" );
823 Sequence< sal_Int16 > aSelection;
824 if( aCtrlProp.GetProperty( aSelection, "SelectedItems" ) )
825 {
826 if( aSelection.hasElements() )
827 {
828 mnSelEntry = aSelection[ 0 ] + 1;
829 comphelper::sequenceToContainer(maMultiSel, aSelection);
830 }
831 }
832
833 // convert listbox with dropdown button to Excel dropdown
834 if( aCtrlProp.GetBoolProperty( "Dropdown" ) )
835 mnObjType = EXC_OBJTYPE_DROPDOWN;
836 }
837 break;
838
839 case FormCompType::COMBOBOX:
840 {
841 Sequence< OUString > aStringList;
842 OUString aDefText;
843 if( aCtrlProp.GetProperty( aStringList, "StringItemList" ) &&
844 aCtrlProp.GetProperty( aDefText, "Text" ) &&
845 aStringList.hasElements() && !aDefText.isEmpty() )
846 {
847 auto nIndex = comphelper::findValue(aStringList, aDefText);
848 if( nIndex != -1 )
849 mnSelEntry = static_cast< sal_Int16 >( nIndex + 1 ); // 1-based
850 if( mnSelEntry > 0 )
851 maMultiSel.resize( 1, mnSelEntry - 1 );
852 }
853
854 // convert combobox without dropdown button to Excel listbox
855 if( !aCtrlProp.GetBoolProperty( "Dropdown" ) )
856 mnObjType = EXC_OBJTYPE_LISTBOX;
857 }
858 break;
859
860 case FormCompType::SCROLLBAR:
861 {
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;
875 }
876 break;
877
878 case FormCompType::SPINBUTTON:
879 {
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;
891 }
892 break;
893 }
894
895 {
896 Reference< XControlModel > xCtrlModel = XclControlHelper::GetControlModel( xShape );
897 if( xCtrlModel.is() )
898 {
899 Reference< XBindableValue > xBindable( xCtrlModel, UNO_QUERY );
900 if( xBindable.is() )
901 {
902 Reference< XServiceInfo > xServInfo( xBindable->getValueBinding(), UNO_QUERY );
903 if( xServInfo.is() && xServInfo->supportsService( SC_SERVICENAME_VALBIND ) )
904 {
905 ScfPropertySet aBindProp( xServInfo );
906 CellAddress aApiAddress;
907 if( aBindProp.GetProperty( aApiAddress, SC_UNONAME_BOUNDCELL ) )
908 {
909 ScUnoConversion::FillScAddress( mxCellLinkAddress, aApiAddress );
910 if( SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape( xShape ) )
911 lcl_GetFromTo( rRoot, pSdrObj->GetLogicRect(), mxCellLinkAddress.Tab(), maAreaFrom, maAreaTo, true );
912 }
913 }
914 }
915 }
916 }
917
918 // spreadsheet links
919 ConvertSheetLinks( xShape );
920 }
921
SetMacroLink(const ScriptEventDescriptor & rEvent)922 bool XclExpTbxControlObj::SetMacroLink( const ScriptEventDescriptor& rEvent )
923 {
924 return XclMacroHelper::SetMacroLink( rEvent, meEventType );
925 }
926
WriteSubRecs(XclExpStream & rStrm)927 void XclExpTbxControlObj::WriteSubRecs( XclExpStream& rStrm )
928 {
929 switch( mnObjType )
930 {
931 // *** Push buttons, labels ***
932
933 case EXC_OBJTYPE_BUTTON:
934 case EXC_OBJTYPE_LABEL:
935 // ftMacro - macro link
936 WriteMacroSubRec( rStrm );
937 break;
938
939 // *** Check boxes, option buttons ***
940
941 case EXC_OBJTYPE_CHECKBOX:
942 case EXC_OBJTYPE_OPTIONBUTTON:
943 {
944 // ftCbls - box properties
945 sal_uInt16 nStyle = 0;
946 ::set_flag( nStyle, EXC_OBJ_CHECKBOX_FLAT, mbFlatButton );
947
948 rStrm.StartRecord( EXC_ID_OBJCBLS, 12 );
949 rStrm << mnState;
950 rStrm.WriteZeroBytes( 8 );
951 rStrm << nStyle;
952 rStrm.EndRecord();
953
954 // ftMacro - macro link
955 WriteMacroSubRec( rStrm );
956 // ftCblsFmla subrecord - cell link
957 WriteCellLinkSubRec( rStrm, EXC_ID_OBJCBLSFMLA );
958
959 // ftCblsData subrecord - box properties, again
960 rStrm.StartRecord( EXC_ID_OBJCBLS, 8 );
961 rStrm << mnState;
962 rStrm.WriteZeroBytes( 4 );
963 rStrm << nStyle;
964 rStrm.EndRecord();
965 }
966 break;
967
968 // *** List boxes, combo boxes ***
969
970 case EXC_OBJTYPE_LISTBOX:
971 case EXC_OBJTYPE_DROPDOWN:
972 {
973 sal_uInt16 nEntryCount = GetSourceEntryCount();
974
975 // ftSbs subrecord - Scroll bars
976 sal_Int32 nLineHeight = XclTools::GetHmmFromTwips( 200 ); // always 10pt
977 if( mnObjType == EXC_OBJTYPE_LISTBOX )
978 mnLineCount = static_cast< sal_uInt16 >( mnHeight / nLineHeight );
979 mnScrollValue = 0;
980 mnScrollMin = 0;
981 sal_uInt16 nInvisLines = (nEntryCount >= mnLineCount) ? (nEntryCount - mnLineCount) : 0;
982 mnScrollMax = limit_cast< sal_uInt16 >( nInvisLines, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
983 mnScrollStep = 1;
984 mnScrollPage = limit_cast< sal_uInt16 >( mnLineCount, EXC_OBJ_SCROLLBAR_MIN, EXC_OBJ_SCROLLBAR_MAX );
985 mbScrollHor = false;
986 WriteSbs( rStrm );
987
988 // ftMacro - macro link
989 WriteMacroSubRec( rStrm );
990 // ftSbsFmla subrecord - cell link
991 WriteCellLinkSubRec( rStrm, EXC_ID_OBJSBSFMLA );
992
993 // ftLbsData - source data range and box properties
994 sal_uInt16 nStyle = 0;
995 ::insert_value( nStyle, mbMultiSel ? EXC_OBJ_LISTBOX_MULTI : EXC_OBJ_LISTBOX_SINGLE, 4, 2 );
996 ::set_flag( nStyle, EXC_OBJ_LISTBOX_FLAT, mbFlatBorder );
997
998 rStrm.StartRecord( EXC_ID_OBJLBSDATA, 0 );
999
1000 if( const XclTokenArray* pSrcRange = GetSourceRangeTokArr() )
1001 {
1002 rStrm << static_cast< sal_uInt16 >( (pSrcRange->GetSize() + 7) & 0xFFFE );
1003 WriteFormula( rStrm, *pSrcRange );
1004 }
1005 else
1006 rStrm << sal_uInt16( 0 );
1007
1008 rStrm << nEntryCount << mnSelEntry << nStyle << sal_uInt16( 0 );
1009 if( mnObjType == EXC_OBJTYPE_LISTBOX )
1010 {
1011 if( nEntryCount )
1012 {
1013 ScfUInt8Vec aSelEx( nEntryCount, 0 );
1014 for( const auto& rItem : maMultiSel )
1015 if( rItem < nEntryCount )
1016 aSelEx[ rItem ] = 1;
1017 rStrm.Write( aSelEx.data(), aSelEx.size() );
1018 }
1019 }
1020 else if( mnObjType == EXC_OBJTYPE_DROPDOWN )
1021 {
1022 rStrm << sal_uInt16( 0 ) << mnLineCount << sal_uInt16( 0 ) << sal_uInt16( 0 );
1023 }
1024
1025 rStrm.EndRecord();
1026 }
1027 break;
1028
1029 // *** Spin buttons, scrollbars ***
1030
1031 case EXC_OBJTYPE_SPIN:
1032 case EXC_OBJTYPE_SCROLLBAR:
1033 {
1034 // ftSbs subrecord - scroll bars
1035 WriteSbs( rStrm );
1036 // ftMacro - macro link
1037 WriteMacroSubRec( rStrm );
1038 // ftSbsFmla subrecord - cell link
1039 WriteCellLinkSubRec( rStrm, EXC_ID_OBJSBSFMLA );
1040 }
1041 break;
1042
1043 // *** Group boxes ***
1044
1045 case EXC_OBJTYPE_GROUPBOX:
1046 {
1047 // ftMacro - macro link
1048 WriteMacroSubRec( rStrm );
1049
1050 // ftGboData subrecord - group box properties
1051 sal_uInt16 nStyle = 0;
1052 ::set_flag( nStyle, EXC_OBJ_GROUPBOX_FLAT, mbFlatBorder );
1053
1054 rStrm.StartRecord( EXC_ID_OBJGBODATA, 6 );
1055 rStrm << sal_uInt32( 0 )
1056 << nStyle;
1057 rStrm.EndRecord();
1058 }
1059 break;
1060 }
1061 }
1062
WriteCellLinkSubRec(XclExpStream & rStrm,sal_uInt16 nSubRecId)1063 void XclExpTbxControlObj::WriteCellLinkSubRec( XclExpStream& rStrm, sal_uInt16 nSubRecId )
1064 {
1065 if( const XclTokenArray* pCellLink = GetCellLinkTokArr() )
1066 WriteFormulaSubRec( rStrm, nSubRecId, *pCellLink );
1067 }
1068
WriteSbs(XclExpStream & rStrm)1069 void XclExpTbxControlObj::WriteSbs( XclExpStream& rStrm )
1070 {
1071 sal_uInt16 nOrient = 0;
1072 ::set_flag( nOrient, EXC_OBJ_SCROLLBAR_HOR, mbScrollHor );
1073 sal_uInt16 nStyle = EXC_OBJ_SCROLLBAR_DEFFLAGS;
1074 ::set_flag( nStyle, EXC_OBJ_SCROLLBAR_FLAT, mbFlatButton );
1075
1076 rStrm.StartRecord( EXC_ID_OBJSBS, 20 );
1077 rStrm << sal_uInt32( 0 ) // reserved
1078 << mnScrollValue // thumb position
1079 << mnScrollMin // thumb min pos
1080 << mnScrollMax // thumb max pos
1081 << mnScrollStep // line increment
1082 << mnScrollPage // page increment
1083 << nOrient // 0 = vertical, 1 = horizontal
1084 << sal_uInt16( 15 ) // thumb width
1085 << nStyle; // flags/style
1086 rStrm.EndRecord();
1087 }
1088
setShapeId(sal_Int32 aShapeId)1089 void XclExpTbxControlObj::setShapeId(sal_Int32 aShapeId)
1090 {
1091 mnShapeId = aShapeId;
1092 }
1093
1094 // save into xl\drawings\drawing1.xml
SaveXml(XclExpXmlStream & rStrm)1095 void XclExpTbxControlObj::SaveXml( XclExpXmlStream& rStrm )
1096 {
1097 sax_fastparser::FSHelperPtr& pDrawing = rStrm.GetCurrentStream();
1098
1099 pDrawing->startElement(FSNS(XML_mc, XML_AlternateContent),
1100 FSNS(XML_xmlns, XML_mc), rStrm.getNamespaceURL(OOX_NS(mce)).toUtf8());
1101 pDrawing->startElement(FSNS(XML_mc, XML_Choice),
1102 FSNS(XML_xmlns, XML_a14), rStrm.getNamespaceURL(OOX_NS(a14)).toUtf8(),
1103 XML_Requires, "a14");
1104
1105 pDrawing->startElement(FSNS(XML_xdr, XML_twoCellAnchor), XML_editAs, "oneCell");
1106 {
1107 pDrawing->startElement(FSNS(XML_xdr, XML_from));
1108 lcl_WriteAnchorVertex(pDrawing, maAreaFrom);
1109 pDrawing->endElement(FSNS(XML_xdr, XML_from));
1110 pDrawing->startElement(FSNS(XML_xdr, XML_to));
1111 lcl_WriteAnchorVertex(pDrawing, maAreaTo);
1112 pDrawing->endElement(FSNS(XML_xdr, XML_to));
1113
1114 pDrawing->startElement(FSNS(XML_xdr, XML_sp));
1115 {
1116 // xdr:nvSpPr
1117 pDrawing->startElement(FSNS(XML_xdr, XML_nvSpPr));
1118 {
1119 pDrawing->singleElement(FSNS(XML_xdr, XML_cNvPr),
1120 XML_id, OString::number(mnShapeId).getStr(),
1121 XML_name, msCtrlName.toUtf8(), // control name
1122 XML_descr, msLabel.toUtf8(), // description as alt text
1123 XML_hidden, mbVisible ? "0" : "1");
1124 pDrawing->singleElement(FSNS(XML_xdr, XML_cNvSpPr));
1125 }
1126 pDrawing->endElement(FSNS(XML_xdr, XML_nvSpPr));
1127
1128 // xdr:spPr
1129 pDrawing->startElement(FSNS(XML_xdr, XML_spPr));
1130 {
1131 // a:xfrm
1132 pDrawing->startElement(FSNS(XML_a, XML_xfrm));
1133 {
1134 pDrawing->singleElement(FSNS(XML_a, XML_off),
1135 XML_x, "0",
1136 XML_y, "0");
1137 pDrawing->singleElement(FSNS(XML_a, XML_ext),
1138 XML_cx, "0",
1139 XML_cy, "0");
1140 }
1141 pDrawing->endElement(FSNS(XML_a, XML_xfrm));
1142
1143 // a:prstGeom
1144 pDrawing->startElement(FSNS(XML_a, XML_prstGeom), XML_prst, "rect");
1145 {
1146 pDrawing->singleElement(FSNS(XML_a, XML_avLst));
1147 }
1148 pDrawing->endElement(FSNS(XML_a, XML_prstGeom));
1149 }
1150 pDrawing->endElement(FSNS(XML_xdr, XML_spPr));
1151
1152 // xdr:txBody
1153 {
1154 pDrawing->startElement(FSNS(XML_xdr, XML_txBody));
1155
1156 #define DEFLRINS 254
1157 #define DEFTBINS 127
1158 sal_Int32 nLeft, nRight, nTop, nBottom;
1159 nLeft = nRight = DEFLRINS;
1160 nTop = nBottom = DEFTBINS;
1161
1162 // top inset looks a bit different compared to ppt export
1163 // check if something related doesn't work as expected
1164 Reference< XPropertySet > rXPropSet(mxShape, UNO_QUERY);
1165
1166 try
1167 {
1168 css::uno::Any mAny;
1169
1170 mAny = rXPropSet->getPropertyValue("TextLeftDistance");
1171 if (mAny.hasValue())
1172 mAny >>= nLeft;
1173
1174 mAny = rXPropSet->getPropertyValue("TextRightDistance");
1175 if (mAny.hasValue())
1176 mAny >>= nRight;
1177
1178 mAny = rXPropSet->getPropertyValue("TextUpperDistance");
1179 if (mAny.hasValue())
1180 mAny >>= nTop;
1181
1182 mAny = rXPropSet->getPropertyValue("TextLowerDistance");
1183 if (mAny.hasValue())
1184 mAny >>= nBottom;
1185 }
1186 catch (...)
1187 {
1188 }
1189
1190 // Specifies the inset of the bounding rectangle.
1191 // Insets are used just as internal margins for text boxes within shapes.
1192 // If this attribute is omitted, then a value of 45720 or 0.05 inches is implied.
1193 pDrawing->startElementNS(XML_a, XML_bodyPr,
1194 XML_lIns, (nLeft != DEFLRINS) ? OString::number(oox::drawingml::convertHmmToEmu(nLeft)).getStr() : nullptr,
1195 XML_rIns, (nRight != DEFLRINS) ? OString::number(oox::drawingml::convertHmmToEmu(nRight)).getStr() : nullptr,
1196 XML_tIns, (nTop != DEFTBINS) ? OString::number(oox::drawingml::convertHmmToEmu(nTop)).getStr() : nullptr,
1197 XML_bIns, (nBottom != DEFTBINS) ? OString::number(oox::drawingml::convertHmmToEmu(nBottom)).getStr() : nullptr,
1198 XML_anchor, "ctr");
1199
1200 {
1201 bool bTextAutoGrowHeight = false;
1202
1203 try
1204 {
1205 css::uno::Any mAny;
1206
1207 mAny = rXPropSet->getPropertyValue("TextAutoGrowHeight");
1208 if (mAny.hasValue())
1209 mAny >>= bTextAutoGrowHeight;
1210 }
1211 catch (...)
1212 {
1213 }
1214
1215 pDrawing->singleElementNS(XML_a, (bTextAutoGrowHeight ? XML_spAutoFit : XML_noAutofit));
1216 }
1217
1218 pDrawing->endElementNS(XML_a, XML_bodyPr);
1219
1220 {
1221 pDrawing->startElementNS(XML_a, XML_p);
1222 pDrawing->startElementNS(XML_a, XML_r);
1223 pDrawing->startElementNS(XML_a, XML_t);
1224 pDrawing->write(msLabel.toUtf8());
1225 pDrawing->endElementNS(XML_a, XML_t);
1226 pDrawing->endElementNS(XML_a, XML_r);
1227 pDrawing->endElementNS(XML_a, XML_p);
1228 }
1229
1230 pDrawing->endElement(FSNS(XML_xdr, XML_txBody));
1231 }
1232 }
1233 pDrawing->endElement(FSNS(XML_xdr, XML_sp));
1234 pDrawing->singleElement(FSNS(XML_xdr, XML_clientData));
1235 }
1236 pDrawing->endElement(FSNS(XML_xdr, XML_twoCellAnchor));
1237 pDrawing->endElement( FSNS( XML_mc, XML_Choice ) );
1238 pDrawing->endElement( FSNS( XML_mc, XML_AlternateContent ) );
1239 }
1240
1241 // output into ctrlProp1.xml
SaveControlPropertiesXml(XclExpXmlStream & rStrm) const1242 OUString XclExpTbxControlObj::SaveControlPropertiesXml(XclExpXmlStream& rStrm) const
1243 {
1244 OUString sIdFormControlPr;
1245
1246 switch (mnObjType)
1247 {
1248 case EXC_OBJTYPE_CHECKBOX:
1249 {
1250 const sal_Int32 nDrawing = XclExpObjList::getNewDrawingUniqueId();
1251 sax_fastparser::FSHelperPtr pFormControl = rStrm.CreateOutputStream(
1252 XclXmlUtils::GetStreamName( "xl/", "ctrlProps/ctrlProps", nDrawing ),
1253 XclXmlUtils::GetStreamName( "../", "ctrlProps/ctrlProps", nDrawing ),
1254 rStrm.GetCurrentStream()->getOutputStream(),
1255 "application/vnd.ms-excel.controlproperties+xml",
1256 OUStringToOString(oox::getRelationship(Relationship::CTRLPROP), RTL_TEXTENCODING_UTF8).getStr(),
1257 &sIdFormControlPr );
1258
1259 rStrm.PushStream( pFormControl );
1260 // checkbox
1261 // <formControlPr
1262 // xmlns="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"
1263 // objectType="CheckBox" checked="Checked" lockText="1" noThreeD="1"/>
1264 //
1265 pFormControl->write("<formControlPr xmlns=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/main\" objectType=\"CheckBox\"");
1266 if (mnState == EXC_OBJ_CHECKBOX_CHECKED)
1267 pFormControl->write(" checked=\"Checked\"");
1268
1269 pFormControl->write(" autoLine=\"false\"");
1270
1271 if (mbPrint)
1272 pFormControl->write(" print=\"true\"");
1273 else
1274 pFormControl->write(" print=\"false\"");
1275
1276 if (mxCellLinkAddress.IsValid())
1277 {
1278 OUString aCellLink = mxCellLinkAddress.Format(ScRefFlags::ADDR_ABS,
1279 &GetDoc(),
1280 ScAddress::Details(::formula::FormulaGrammar::CONV_XL_A1));
1281
1282 // "Sheet1!$C$5"
1283 pFormControl->write(" fmlaLink=\"");
1284 if (aCellLink.indexOf('!') < 0)
1285 {
1286 pFormControl->write(GetTabInfo().GetScTabName( mxCellLinkAddress.Tab() ).toUtf8());
1287 pFormControl->write("!");
1288 }
1289 pFormControl->write(aCellLink);
1290 pFormControl->write("\"");
1291 }
1292
1293 pFormControl->write(" lockText=\"1\" noThreeD=\"1\"/>");
1294 rStrm.PopStream();
1295
1296 break;
1297 }
1298 }
1299
1300 return sIdFormControlPr;
1301 }
1302
1303 // output into sheet1.xml
SaveSheetXml(XclExpXmlStream & rStrm,const OUString & aIdFormControlPr) const1304 void XclExpTbxControlObj::SaveSheetXml(XclExpXmlStream& rStrm, const OUString& aIdFormControlPr) const
1305 {
1306 switch (mnObjType)
1307 {
1308 case EXC_OBJTYPE_CHECKBOX:
1309 {
1310 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1311
1312 rWorksheet->startElement(FSNS(XML_mc, XML_AlternateContent),
1313 FSNS(XML_xmlns, XML_mc), rStrm.getNamespaceURL(OOX_NS(mce)).toUtf8());
1314 rWorksheet->startElement(FSNS(XML_mc, XML_Choice), XML_Requires, "x14");
1315
1316 rWorksheet->startElement(
1317 XML_control,
1318 XML_shapeId, OString::number(mnShapeId).getStr(),
1319 FSNS(XML_r, XML_id), aIdFormControlPr.toUtf8(),
1320 XML_name, msLabel.toUtf8()); // text to display with checkbox button
1321
1322 rWorksheet->write("<controlPr defaultSize=\"0\" locked=\"1\" autoFill=\"0\" autoLine=\"0\" autoPict=\"0\"");
1323
1324 if (mbPrint)
1325 rWorksheet->write(" print=\"true\"");
1326 else
1327 rWorksheet->write(" print=\"false\"");
1328
1329 if (!msCtrlName.isEmpty())
1330 {
1331 rWorksheet->write(" altText=\"");
1332 rWorksheet->write(msCtrlName.toUtf8()); // alt text
1333 rWorksheet->write("\"");
1334 }
1335
1336 rWorksheet->write(">");
1337
1338 rWorksheet->startElement(XML_anchor, XML_moveWithCells, "true", XML_sizeWithCells, "false");
1339 rWorksheet->startElement(XML_from);
1340 lcl_WriteAnchorVertex(rWorksheet, maAreaFrom);
1341 rWorksheet->endElement(XML_from);
1342 rWorksheet->startElement(XML_to);
1343 lcl_WriteAnchorVertex(rWorksheet, maAreaTo);
1344 rWorksheet->endElement(XML_to);
1345 rWorksheet->endElement( XML_anchor );
1346
1347 rWorksheet->write("</controlPr>");
1348
1349 rWorksheet->endElement(XML_control);
1350 rWorksheet->endElement( FSNS( XML_mc, XML_Choice ) );
1351 rWorksheet->endElement( FSNS( XML_mc, XML_AlternateContent ) );
1352
1353 break;
1354 }
1355 }
1356 }
1357
1358 //#endif
1359
XclExpChartObj(XclExpObjectManager & rObjMgr,Reference<XShape> const & xShape,const tools::Rectangle * pChildAnchor,ScDocument * pDoc)1360 XclExpChartObj::XclExpChartObj( XclExpObjectManager& rObjMgr, Reference< XShape > const & xShape, const tools::Rectangle* pChildAnchor, ScDocument* pDoc ) :
1361 XclObj( rObjMgr, EXC_OBJTYPE_CHART ),
1362 XclExpRoot( rObjMgr.GetRoot() ), mxShape( xShape ),
1363 mpDoc(pDoc)
1364 {
1365 // create the MSODRAWING record contents for the chart object
1366 mrEscherEx.OpenContainer( ESCHER_SpContainer );
1367 mrEscherEx.AddShape( ESCHER_ShpInst_HostControl, ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty );
1368 EscherPropertyContainer aPropOpt;
1369 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x01040104 );
1370 aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x00080008 );
1371 aPropOpt.AddOpt( ESCHER_Prop_fillColor, 0x0800004E );
1372 aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x0800004D );
1373 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x00110010 );
1374 aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x0800004D );
1375 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080008 );
1376 aPropOpt.AddOpt( ESCHER_Prop_fshadowObscured, 0x00020000 );
1377 aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x00080000 );
1378 aPropOpt.Commit( mrEscherEx.GetStream() );
1379
1380 // anchor
1381 SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape( xShape );
1382 ImplWriteAnchor( pSdrObj, pChildAnchor );
1383
1384 // client data (the following OBJ record)
1385 mrEscherEx.AddAtom( 0, ESCHER_ClientData );
1386 mrEscherEx.CloseContainer(); // ESCHER_SpContainer
1387 mrEscherEx.UpdateDffFragmentEnd();
1388
1389 // load the chart OLE object
1390 if( SdrOle2Obj* pSdrOleObj = dynamic_cast< SdrOle2Obj* >( pSdrObj ) )
1391 svt::EmbeddedObjectRef::TryRunningState( pSdrOleObj->GetObjRef() );
1392
1393 // create the chart substream object
1394 ScfPropertySet aShapeProp( xShape );
1395 Reference< XModel > xModel;
1396 aShapeProp.GetProperty( xModel, "Model" );
1397 mxChartDoc.set( xModel,UNO_QUERY );
1398 css::awt::Rectangle aBoundRect;
1399 aShapeProp.GetProperty( aBoundRect, "BoundRect" );
1400 tools::Rectangle aChartRect( Point( aBoundRect.X, aBoundRect.Y ), Size( aBoundRect.Width, aBoundRect.Height ) );
1401 mxChart.reset( new XclExpChart( GetRoot(), xModel, aChartRect ) );
1402 }
1403
~XclExpChartObj()1404 XclExpChartObj::~XclExpChartObj()
1405 {
1406 }
1407
Save(XclExpStream & rStrm)1408 void XclExpChartObj::Save( XclExpStream& rStrm )
1409 {
1410 // content of OBJ record
1411 XclObj::Save( rStrm );
1412 // chart substream
1413 mxChart->Save( rStrm );
1414 }
1415
SaveXml(XclExpXmlStream & rStrm)1416 void XclExpChartObj::SaveXml( XclExpXmlStream& rStrm )
1417 {
1418 sax_fastparser::FSHelperPtr pDrawing = rStrm.GetCurrentStream();
1419
1420 // FIXME: two cell? it seems the two cell anchor is incorrect.
1421 pDrawing->startElement( FSNS( XML_xdr, XML_twoCellAnchor ), // OOXTODO: oneCellAnchor, absoluteAnchor
1422 XML_editAs, "oneCell" );
1423 Reference< XPropertySet > xPropSet( mxShape, UNO_QUERY );
1424 if (xPropSet.is())
1425 {
1426 XclObjAny::WriteFromTo( rStrm, mxShape, GetTab() );
1427 ChartExport aChartExport(XML_xdr, pDrawing, mxChartDoc, &rStrm, drawingml::DOCUMENT_XLSX);
1428 std::shared_ptr<oox::drawingml::URLTransformer> pURLTransformer(new ScURLTransformer(*mpDoc));
1429 aChartExport.SetURLTranslator(pURLTransformer);
1430 static sal_Int32 nChartCount = 0;
1431 nChartCount++;
1432 sal_Int32 nID = rStrm.GetUniqueId();
1433 aChartExport.WriteChartObj( mxShape, nID, nChartCount );
1434 // TODO: get the correcto chart number
1435 }
1436
1437 pDrawing->singleElement( FSNS( XML_xdr, XML_clientData)
1438 // OOXTODO: XML_fLocksWithSheet
1439 // OOXTODO: XML_fPrintsWithSheet
1440 );
1441 pDrawing->endElement( FSNS( XML_xdr, XML_twoCellAnchor ) );
1442 }
1443
GetChartDoc() const1444 const css::uno::Reference<css::chart::XChartDocument>& XclExpChartObj::GetChartDoc() const
1445 {
1446 return mxChartDoc;
1447 }
1448
XclExpNote(const XclExpRoot & rRoot,const ScAddress & rScPos,const ScPostIt * pScNote,const OUString & rAddText)1449 XclExpNote::XclExpNote(const XclExpRoot& rRoot, const ScAddress& rScPos,
1450 const ScPostIt* pScNote, const OUString& rAddText)
1451 : XclExpRecord(EXC_ID_NOTE)
1452 , mrRoot(rRoot)
1453 , maScPos(rScPos)
1454 , mnObjId(EXC_OBJ_INVALID_ID)
1455 , mbVisible(pScNote && pScNote->IsCaptionShown())
1456 , meTHA(SDRTEXTHORZADJUST_LEFT)
1457 , meTVA(SDRTEXTVERTADJUST_TOP)
1458 , mbAutoScale(false)
1459 , mbLocked(false)
1460 , mbAutoFill(false)
1461 , mbColHidden(false)
1462 , mbRowHidden(false)
1463 {
1464 // get the main note text
1465 OUString aNoteText;
1466 if( pScNote )
1467 {
1468 aNoteText = pScNote->GetText();
1469 const EditTextObject *pEditObj = pScNote->GetEditTextObject();
1470 if( pEditObj )
1471 mpNoteContents = XclExpStringHelper::CreateString( rRoot, *pEditObj );
1472 }
1473 // append additional text
1474 aNoteText = ScGlobal::addToken( aNoteText, rAddText, '\n', 2 );
1475
1476 // initialize record dependent on BIFF type
1477 switch( rRoot.GetBiff() )
1478 {
1479 case EXC_BIFF5:
1480 maNoteText = OUStringToOString(aNoteText, rRoot.GetTextEncoding());
1481 break;
1482
1483 case EXC_BIFF8:
1484 {
1485 // TODO: additional text
1486 if( pScNote )
1487 {
1488 if( SdrCaptionObj* pCaption = pScNote->GetOrCreateCaption( maScPos ) )
1489 {
1490 lcl_GetFromTo( rRoot, pCaption->GetLogicRect(), maScPos.Tab(), maCommentFrom, maCommentTo );
1491 if( const OutlinerParaObject* pOPO = pCaption->GetOutlinerParaObject() )
1492 mnObjId = rRoot.GetObjectManager().AddObj( std::make_unique<XclObjComment>( rRoot.GetObjectManager(), pCaption->GetLogicRect(), pOPO->GetTextObject(), pCaption, mbVisible, maScPos, maCommentFrom, maCommentTo ) );
1493
1494 SfxItemSet aItemSet = pCaption->GetMergedItemSet();
1495 meTVA = pCaption->GetTextVerticalAdjust();
1496 meTHA = pCaption->GetTextHorizontalAdjust();
1497 mbAutoScale = pCaption->GetFitToSize() != drawing::TextFitToSizeType_NONE;
1498 mbLocked = pCaption->IsMoveProtect() || pCaption->IsResizeProtect();
1499
1500 // AutoFill style would change if Postit.cxx object creation values are changed
1501 OUString aCol(aItemSet.Get(XATTR_FILLCOLOR).GetValue());
1502 mbAutoFill = aCol.isEmpty() && (aItemSet.Get(XATTR_FILLSTYLE).GetValue() == drawing::FillStyle_SOLID);
1503 mbRowHidden = (rRoot.GetDoc().RowHidden(maScPos.Row(),maScPos.Tab()));
1504 mbColHidden = (rRoot.GetDoc().ColHidden(maScPos.Col(),maScPos.Tab()));
1505 }
1506 // stAuthor (variable): An XLUnicodeString that specifies the name of the comment
1507 // author. String length MUST be greater than or equal to 1 and less than or equal
1508 // to 54.
1509 if( pScNote->GetAuthor().isEmpty() )
1510 maAuthor = XclExpString( " " );
1511 else
1512 maAuthor = XclExpString( pScNote->GetAuthor(), XclStrFlags::NONE, 54 );
1513 }
1514
1515 SetRecSize( 9 + maAuthor.GetSize() );
1516 }
1517 break;
1518
1519 default: DBG_ERROR_BIFF();
1520 }
1521 }
1522
Save(XclExpStream & rStrm)1523 void XclExpNote::Save( XclExpStream& rStrm )
1524 {
1525 switch( rStrm.GetRoot().GetBiff() )
1526 {
1527 case EXC_BIFF5:
1528 {
1529 // write the NOTE record directly, there may be the need to create more than one
1530 const sal_Char* pcBuffer = maNoteText.getStr();
1531 sal_uInt16 nCharsLeft = static_cast< sal_uInt16 >( maNoteText.getLength() );
1532
1533 while( nCharsLeft )
1534 {
1535 sal_uInt16 nWriteChars = ::std::min( nCharsLeft, EXC_NOTE5_MAXLEN );
1536
1537 rStrm.StartRecord( EXC_ID_NOTE, 6 + nWriteChars );
1538 if( pcBuffer == maNoteText.getStr() )
1539 {
1540 // first record: row, col, length of complete text
1541 rStrm << static_cast< sal_uInt16 >( maScPos.Row() )
1542 << static_cast< sal_uInt16 >( maScPos.Col() )
1543 << nCharsLeft; // still contains full length
1544 }
1545 else
1546 {
1547 // next records: -1, 0, length of current text segment
1548 rStrm << sal_uInt16( 0xFFFF )
1549 << sal_uInt16( 0 )
1550 << nWriteChars;
1551 }
1552 rStrm.Write( pcBuffer, nWriteChars );
1553 rStrm.EndRecord();
1554
1555 pcBuffer += nWriteChars;
1556 nCharsLeft = nCharsLeft - nWriteChars;
1557 }
1558 }
1559 break;
1560
1561 case EXC_BIFF8:
1562 if( mnObjId != EXC_OBJ_INVALID_ID )
1563 XclExpRecord::Save( rStrm );
1564 break;
1565
1566 default: DBG_ERROR_BIFF();
1567 }
1568 }
1569
WriteBody(XclExpStream & rStrm)1570 void XclExpNote::WriteBody( XclExpStream& rStrm )
1571 {
1572 // BIFF5/BIFF7 is written separately
1573 OSL_ENSURE_BIFF( rStrm.GetRoot().GetBiff() == EXC_BIFF8 );
1574
1575 sal_uInt16 nFlags = 0;
1576 ::set_flag( nFlags, EXC_NOTE_VISIBLE, mbVisible );
1577
1578 rStrm << static_cast< sal_uInt16 >( maScPos.Row() )
1579 << static_cast< sal_uInt16 >( maScPos.Col() )
1580 << nFlags
1581 << mnObjId
1582 << maAuthor
1583 << sal_uInt8( 0 );
1584 }
1585
WriteXml(sal_Int32 nAuthorId,XclExpXmlStream & rStrm)1586 void XclExpNote::WriteXml( sal_Int32 nAuthorId, XclExpXmlStream& rStrm )
1587 {
1588 sax_fastparser::FSHelperPtr rComments = rStrm.GetCurrentStream();
1589
1590 rComments->startElement( XML_comment,
1591 XML_ref, XclXmlUtils::ToOString(&mrRoot.GetDoc(), maScPos),
1592 XML_authorId, OString::number(nAuthorId)
1593 // OOXTODO: XML_guid
1594 );
1595 rComments->startElement(XML_text);
1596 // OOXTODO: phoneticPr, rPh, r
1597 if( mpNoteContents )
1598 mpNoteContents->WriteXml( rStrm );
1599 rComments->endElement( XML_text );
1600
1601 /*
1602 Export of commentPr is disabled, since the current (Oct 2010)
1603 version of MSO 2010 doesn't yet support commentPr
1604 */
1605 #if 1//def XLSX_OOXML_FUTURE
1606 if( rStrm.getVersion() == oox::core::ISOIEC_29500_2008 )
1607 {
1608 rComments->startElement(FSNS(XML_mc, XML_AlternateContent));
1609 rComments->startElement(FSNS(XML_mc, XML_Choice), XML_Requires, "v2");
1610 rComments->startElement( XML_commentPr,
1611 XML_autoFill, ToPsz( mbAutoFill ),
1612 XML_autoScale, ToPsz( mbAutoScale ),
1613 XML_colHidden, ToPsz( mbColHidden ),
1614 XML_locked, ToPsz( mbLocked ),
1615 XML_rowHidden, ToPsz( mbRowHidden ),
1616 XML_textHAlign, ToHorizAlign( meTHA ),
1617 XML_textVAlign, ToVertAlign( meTVA ) );
1618 rComments->startElement(XML_anchor, XML_moveWithCells, "false", XML_sizeWithCells, "false");
1619 rComments->startElement(FSNS(XML_xdr, XML_from));
1620 lcl_WriteAnchorVertex( rComments, maCommentFrom );
1621 rComments->endElement( FSNS( XML_xdr, XML_from ) );
1622 rComments->startElement(FSNS(XML_xdr, XML_to));
1623 lcl_WriteAnchorVertex( rComments, maCommentTo );
1624 rComments->endElement( FSNS( XML_xdr, XML_to ) );
1625 rComments->endElement( XML_anchor );
1626 rComments->endElement( XML_commentPr );
1627
1628 rComments->endElement( FSNS( XML_mc, XML_Choice ) );
1629 rComments->startElement(FSNS(XML_mc, XML_Fallback));
1630 // Any fallback code ?
1631 rComments->endElement( FSNS( XML_mc, XML_Fallback ) );
1632 rComments->endElement( FSNS( XML_mc, XML_AlternateContent ) );
1633 }
1634 #endif
1635 rComments->endElement( XML_comment );
1636 }
1637
XclMacroHelper(const XclExpRoot & rRoot)1638 XclMacroHelper::XclMacroHelper( const XclExpRoot& rRoot ) :
1639 XclExpControlHelper( rRoot )
1640 {
1641 }
1642
~XclMacroHelper()1643 XclMacroHelper::~XclMacroHelper()
1644 {
1645 }
1646
WriteMacroSubRec(XclExpStream & rStrm)1647 void XclMacroHelper::WriteMacroSubRec( XclExpStream& rStrm )
1648 {
1649 if( mxMacroLink )
1650 WriteFormulaSubRec( rStrm, EXC_ID_OBJMACRO, *mxMacroLink );
1651 }
1652
1653 bool
SetMacroLink(const ScriptEventDescriptor & rEvent,const XclTbxEventType & nEventType)1654 XclMacroHelper::SetMacroLink( const ScriptEventDescriptor& rEvent, const XclTbxEventType& nEventType )
1655 {
1656 OUString aMacroName = XclControlHelper::ExtractFromMacroDescriptor( rEvent, nEventType );
1657 if( !aMacroName.isEmpty() )
1658 {
1659 return SetMacroLink( aMacroName );
1660 }
1661 return false;
1662 }
1663
1664 bool
SetMacroLink(const OUString & rMacroName)1665 XclMacroHelper::SetMacroLink( const OUString& rMacroName )
1666 {
1667 if( !rMacroName.isEmpty() )
1668 {
1669 sal_uInt16 nExtSheet = GetLocalLinkManager().FindExtSheet( EXC_EXTSH_OWNDOC );
1670 sal_uInt16 nNameIdx = GetNameManager().InsertMacroCall( rMacroName, true, false );
1671 mxMacroLink = GetFormulaCompiler().CreateNameXFormula( nExtSheet, nNameIdx );
1672 return true;
1673 }
1674 return false;
1675 }
1676
XclExpShapeObj(XclExpObjectManager & rRoot,css::uno::Reference<css::drawing::XShape> const & xShape,ScDocument * pDoc)1677 XclExpShapeObj::XclExpShapeObj( XclExpObjectManager& rRoot, css::uno::Reference< css::drawing::XShape > const & xShape, ScDocument* pDoc ) :
1678 XclObjAny( rRoot, xShape, pDoc ),
1679 XclMacroHelper( rRoot )
1680 {
1681 if( SdrObject* pSdrObj = ::GetSdrObjectFromXShape( xShape ) )
1682 {
1683 ScMacroInfo* pInfo = ScDrawLayer::GetMacroInfo( pSdrObj );
1684 if ( pInfo && !pInfo->GetMacro().isEmpty() )
1685 // 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
1686 // SetMacroLink( XclControlHelper::GetXclMacroName( pInfo->GetMacro(), rRoot.GetDocShell() ) );
1687 SetMacroLink( XclTools::GetXclMacroName( pInfo->GetMacro() ) );
1688 }
1689 }
1690
~XclExpShapeObj()1691 XclExpShapeObj::~XclExpShapeObj()
1692 {
1693 }
1694
WriteSubRecs(XclExpStream & rStrm)1695 void XclExpShapeObj::WriteSubRecs( XclExpStream& rStrm )
1696 {
1697 XclObjAny::WriteSubRecs( rStrm );
1698 WriteMacroSubRec( rStrm );
1699 }
1700
XclExpComments(SCTAB nTab,XclExpRecordList<XclExpNote> & rNotes)1701 XclExpComments::XclExpComments( SCTAB nTab, XclExpRecordList< XclExpNote >& rNotes )
1702 : mnTab( nTab ), mrNotes( rNotes )
1703 {
1704 }
1705
SaveXml(XclExpXmlStream & rStrm)1706 void XclExpComments::SaveXml( XclExpXmlStream& rStrm )
1707 {
1708 if( mrNotes.IsEmpty() )
1709 return;
1710
1711 sax_fastparser::FSHelperPtr rComments = rStrm.CreateOutputStream(
1712 XclXmlUtils::GetStreamName( "xl/", "comments", mnTab + 1 ),
1713 XclXmlUtils::GetStreamName( "../", "comments", mnTab + 1 ),
1714 rStrm.GetCurrentStream()->getOutputStream(),
1715 "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml",
1716 OUStringToOString(oox::getRelationship(Relationship::COMMENTS), RTL_TEXTENCODING_UTF8).getStr());
1717 rStrm.PushStream( rComments );
1718
1719 if( rStrm.getVersion() == oox::core::ISOIEC_29500_2008 )
1720 rComments->startElement( XML_comments,
1721 XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xls)).toUtf8(),
1722 FSNS(XML_xmlns, XML_mc), rStrm.getNamespaceURL(OOX_NS(mce)).toUtf8(),
1723 FSNS(XML_xmlns, XML_xdr), rStrm.getNamespaceURL(OOX_NS(dmlSpreadDr)).toUtf8(),
1724 FSNS(XML_xmlns, XML_v2), rStrm.getNamespaceURL(OOX_NS(mceTest)).toUtf8(),
1725 FSNS( XML_mc, XML_Ignorable ), "v2" );
1726 else
1727 rComments->startElement( XML_comments,
1728 XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xls)).toUtf8(),
1729 FSNS(XML_xmlns, XML_xdr), rStrm.getNamespaceURL(OOX_NS(dmlSpreadDr)).toUtf8() );
1730
1731 rComments->startElement(XML_authors);
1732
1733 typedef std::set<OUString> Authors;
1734 Authors aAuthors;
1735
1736 size_t nNotes = mrNotes.GetSize();
1737 for( size_t i = 0; i < nNotes; ++i )
1738 {
1739 aAuthors.insert( XclXmlUtils::ToOUString( mrNotes.GetRecord( i )->GetAuthor() ) );
1740 }
1741
1742 for( const auto& rAuthor : aAuthors )
1743 {
1744 rComments->startElement(XML_author);
1745 rComments->writeEscaped( rAuthor );
1746 rComments->endElement( XML_author );
1747 }
1748
1749 rComments->endElement( XML_authors );
1750 rComments->startElement(XML_commentList);
1751
1752 Authors::const_iterator aAuthorsBegin = aAuthors.begin();
1753 for( size_t i = 0; i < nNotes; ++i )
1754 {
1755 XclExpRecordList< XclExpNote >::RecordRefType xNote = mrNotes.GetRecord( i );
1756 Authors::const_iterator aAuthor = aAuthors.find(
1757 XclXmlUtils::ToOUString( xNote->GetAuthor() ) );
1758 sal_Int32 nAuthorId = distance( aAuthorsBegin, aAuthor );
1759 xNote->WriteXml( nAuthorId, rStrm );
1760 }
1761
1762 rComments->endElement( XML_commentList );
1763 rComments->endElement( XML_comments );
1764
1765 rStrm.PopStream();
1766 }
1767
1768 // object manager =============================================================
1769
XclExpObjectManager(const XclExpRoot & rRoot)1770 XclExpObjectManager::XclExpObjectManager( const XclExpRoot& rRoot ) :
1771 XclExpRoot( rRoot )
1772 {
1773 InitStream( true );
1774 mxEscherEx.reset( new XclEscherEx( GetRoot(), *this, *mxDffStrm ) );
1775 }
1776
XclExpObjectManager(const XclExpObjectManager & rParent)1777 XclExpObjectManager::XclExpObjectManager( const XclExpObjectManager& rParent ) :
1778 XclExpRoot( rParent.GetRoot() )
1779 {
1780 InitStream( false );
1781 mxEscherEx.reset( new XclEscherEx( GetRoot(), *this, *mxDffStrm, rParent.mxEscherEx.get() ) );
1782 }
1783
~XclExpObjectManager()1784 XclExpObjectManager::~XclExpObjectManager()
1785 {
1786 }
1787
CreateDffAnchor() const1788 XclExpDffAnchorBase* XclExpObjectManager::CreateDffAnchor() const
1789 {
1790 return new XclExpDffSheetAnchor( GetRoot() );
1791 }
1792
CreateDrawingGroup()1793 std::shared_ptr< XclExpRecordBase > XclExpObjectManager::CreateDrawingGroup()
1794 {
1795 return std::shared_ptr< XclExpRecordBase >( new XclExpMsoDrawingGroup( *mxEscherEx ) );
1796 }
1797
StartSheet()1798 void XclExpObjectManager::StartSheet()
1799 {
1800 mxObjList.reset( new XclExpObjList( GetRoot(), *mxEscherEx ) );
1801 }
1802
ProcessDrawing(const SdrPage * pSdrPage)1803 std::shared_ptr< XclExpRecordBase > XclExpObjectManager::ProcessDrawing( const SdrPage* pSdrPage )
1804 {
1805 if( pSdrPage )
1806 mxEscherEx->AddSdrPage( *pSdrPage );
1807 // the first dummy object may still be open
1808 OSL_ENSURE( mxEscherEx->GetGroupLevel() <= 1, "XclExpObjectManager::ProcessDrawing - still groups open?" );
1809 while( mxEscherEx->GetGroupLevel() )
1810 mxEscherEx->LeaveGroup();
1811 mxObjList->EndSheet();
1812 return mxObjList;
1813 }
1814
ProcessDrawing(const Reference<XShapes> & rxShapes)1815 std::shared_ptr< XclExpRecordBase > XclExpObjectManager::ProcessDrawing( const Reference< XShapes >& rxShapes )
1816 {
1817 if( rxShapes.is() )
1818 mxEscherEx->AddUnoShapes( rxShapes );
1819 // the first dummy object may still be open
1820 OSL_ENSURE( mxEscherEx->GetGroupLevel() <= 1, "XclExpObjectManager::ProcessDrawing - still groups open?" );
1821 while( mxEscherEx->GetGroupLevel() )
1822 mxEscherEx->LeaveGroup();
1823 mxObjList->EndSheet();
1824 return mxObjList;
1825 }
1826
EndDocument()1827 void XclExpObjectManager::EndDocument()
1828 {
1829 mxEscherEx->EndDocument();
1830 }
1831
GetMsodrawingPerSheet()1832 XclExpMsoDrawing* XclExpObjectManager::GetMsodrawingPerSheet()
1833 {
1834 return mxObjList->GetMsodrawingPerSheet();
1835 }
1836
HasObj() const1837 bool XclExpObjectManager::HasObj() const
1838 {
1839 return !mxObjList->empty();
1840 }
1841
AddObj(std::unique_ptr<XclObj> pObjRec)1842 sal_uInt16 XclExpObjectManager::AddObj( std::unique_ptr<XclObj> pObjRec )
1843 {
1844 return mxObjList->Add( std::move(pObjRec) );
1845 }
1846
RemoveLastObj()1847 std::unique_ptr<XclObj> XclExpObjectManager::RemoveLastObj()
1848 {
1849 return mxObjList->pop_back();
1850 }
1851
InitStream(bool bTempFile)1852 void XclExpObjectManager::InitStream( bool bTempFile )
1853 {
1854 if( bTempFile )
1855 {
1856 mxTempFile.reset( new ::utl::TempFile );
1857 if( mxTempFile->IsValid() )
1858 {
1859 mxTempFile->EnableKillingFile();
1860 mxDffStrm = ::utl::UcbStreamHelper::CreateStream( mxTempFile->GetURL(), StreamMode::STD_READWRITE );
1861 }
1862 }
1863
1864 if( !mxDffStrm.get() )
1865 mxDffStrm.reset( new SvMemoryStream );
1866
1867 mxDffStrm->SetEndian( SvStreamEndian::LITTLE );
1868 }
1869
XclExpEmbeddedObjectManager(const XclExpObjectManager & rParent,const Size & rPageSize,sal_Int32 nScaleX,sal_Int32 nScaleY)1870 XclExpEmbeddedObjectManager::XclExpEmbeddedObjectManager(
1871 const XclExpObjectManager& rParent, const Size& rPageSize, sal_Int32 nScaleX, sal_Int32 nScaleY ) :
1872 XclExpObjectManager( rParent ),
1873 maPageSize( rPageSize ),
1874 mnScaleX( nScaleX ),
1875 mnScaleY( nScaleY )
1876 {
1877 }
1878
CreateDffAnchor() const1879 XclExpDffAnchorBase* XclExpEmbeddedObjectManager::CreateDffAnchor() const
1880 {
1881 return new XclExpDffEmbeddedAnchor( GetRoot(), maPageSize, mnScaleX, mnScaleY );
1882 }
1883
1884 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1885