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 "eppt.hxx"
21 #include "epptdef.hxx"
22 #include "pptexanimations.hxx"
23 #include <o3tl/any.hxx>
24 #include <tools/globname.hxx>
25 #include <rtl/ustring.hxx>
26 #include <tools/stream.hxx>
27 #include <svx/unoapi.hxx>
28 #include <svx/svdobj.hxx>
29 #include <svx/svdoole2.hxx>
30 #include <com/sun/star/container/XIndexContainer.hpp>
31 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
32 #include <com/sun/star/drawing/FillStyle.hpp>
33 #include <com/sun/star/frame/XModel.hpp>
34 #include <com/sun/star/office/XAnnotation.hpp>
35 #include <com/sun/star/office/XAnnotationAccess.hpp>
36 #include <com/sun/star/office/XAnnotationEnumeration.hpp>
37 #include <com/sun/star/presentation/AnimationSpeed.hpp>
38 #include <com/sun/star/presentation/XPresentationSupplier.hpp>
39 #include <com/sun/star/presentation/XCustomPresentationSupplier.hpp>
40 #include <com/sun/star/geometry/RealPoint2D.hpp>
41 #include <com/sun/star/util/DateTime.hpp>
42 #include <com/sun/star/task/XStatusIndicator.hpp>
43 #include <comphelper/sequence.hxx>
44 #include <tools/zcodec.hxx>
45 #include <filter/msfilter/classids.hxx>
46 #include <filter/msfilter/msoleexp.hxx>
47 #include <filter/msfilter/msdffimp.hxx>
48 #include <filter/msfilter/svxmsbas.hxx>
49 #include <editeng/flditem.hxx>
50 #include <sfx2/docinf.hxx>
51 #include <oox/export/utils.hxx>
52 #include <oox/ole/olehelper.hxx>
53 #include <memory>
54
55 class SfxObjectShell;
56 // complete SfxObjectShell for SaveVBA under -fsanitize=function
57
58 using namespace com::sun::star;
59 using namespace ::com::sun::star::uno;
60 using namespace ::com::sun::star::presentation;
61
62 using ::com::sun::star::beans::XPropertySet;
63
64 //============================ PPTWriter ==================================
65
PPTWriter(tools::SvRef<SotStorage> const & rSvStorage,css::uno::Reference<css::frame::XModel> const & rXModel,css::uno::Reference<css::task::XStatusIndicator> const & rXStatInd,SvMemoryStream * pVBA,sal_uInt32 nCnvrtFlags)66 PPTWriter::PPTWriter( tools::SvRef<SotStorage> const & rSvStorage,
67 css::uno::Reference< css::frame::XModel > const & rXModel,
68 css::uno::Reference< css::task::XStatusIndicator > const & rXStatInd,
69 SvMemoryStream* pVBA, sal_uInt32 nCnvrtFlags ) :
70 PPTWriterBase ( rXModel, rXStatInd ),
71 mnCnvrtFlags ( nCnvrtFlags ),
72 mbStatus ( false ),
73 mnStatMaxValue ( 0 ),
74 mnLatestStatValue ( 0 ),
75 mnTextStyle( 0 ),
76 mbFontIndependentLineSpacing( false ),
77 mnTextSize( 0 ),
78 mrStg ( rSvStorage ),
79 mnVBAOleOfs ( 0 ),
80 mpVBA ( pVBA ),
81 mnExEmbed ( 0 ),
82 mpExEmbed ( new SvMemoryStream ),
83 mnPagesWritten ( 0 ),
84 mnTxId ( 0x7a2f64 ),
85 mnDiaMode ( 0 ),
86 mnShapeMasterTitle ( 0 ),
87 mnShapeMasterBody ( 0 )
88 {
89 }
90
exportPPTPre(const std::vector<css::beans::PropertyValue> & rMediaData)91 void PPTWriter::exportPPTPre( const std::vector< css::beans::PropertyValue >& rMediaData )
92 {
93 if ( !mrStg.is() )
94 return;
95
96 if ( mXStatusIndicator.is() )
97 {
98 mbStatusIndicator = true;
99 mnStatMaxValue = ( mnPages + mnMasterPages ) * 5;
100 mXStatusIndicator->start( "PowerPoint Export", mnStatMaxValue + ( mnStatMaxValue >> 3 ) );
101 }
102
103 SvGlobalName aGName(MSO_PPT8_CLASSID);
104 mrStg->SetClass( aGName, SotClipboardFormatId::NONE, "MS PowerPoint 97" );
105
106 if ( !ImplCreateCurrentUserStream() )
107 return;
108
109 mpStrm = mrStg->OpenSotStream( "PowerPoint Document" );
110 if ( !mpStrm )
111 return;
112
113 if ( !mpPicStrm )
114 mpPicStrm = mrStg->OpenSotStream( "Pictures" );
115
116 auto aIter = std::find_if(rMediaData.begin(), rMediaData.end(),
117 [](const css::beans::PropertyValue& rProp) { return rProp.Name == "BaseURI"; });
118 if (aIter != rMediaData.end())
119 (*aIter).Value >>= maBaseURI;
120 mpPptEscherEx.reset( new PptEscherEx( *mpStrm, maBaseURI ) );
121 }
122
exportPPTPost()123 void PPTWriter::exportPPTPost( )
124 {
125 if ( !ImplCloseDocument() )
126 return;
127
128 if ( mbStatusIndicator )
129 {
130 mXStatusIndicator->setText( "PowerPoint Export" );
131 sal_uInt32 nValue = mnStatMaxValue + ( mnStatMaxValue >> 3 );
132 if ( nValue > mnLatestStatValue )
133 {
134 mXStatusIndicator->setValue( nValue );
135 mnLatestStatValue = nValue;
136 }
137 }
138
139 ImplWriteOLE();
140
141 ImplWriteVBA();
142
143 ImplWriteAtomEnding();
144
145 ImplCreateDocumentSummaryInformation();
146
147 mbStatus = true;
148 };
149
150 static void ImplExportComments( const uno::Reference< drawing::XDrawPage >& xPage, SvMemoryStream& rBinaryTagData10Atom );
151
ImplWriteSlide(sal_uInt32 nPageNum,sal_uInt32 nMasterNum,sal_uInt16 nMode,bool bHasBackground,Reference<XPropertySet> const & aXBackgroundPropSet)152 void PPTWriter::ImplWriteSlide( sal_uInt32 nPageNum, sal_uInt32 nMasterNum, sal_uInt16 nMode,
153 bool bHasBackground, Reference< XPropertySet > const & aXBackgroundPropSet )
154 {
155 Any aAny;
156
157 const PHLayout& rLayout = GetLayout( mXPagePropSet );
158 mpPptEscherEx->PtReplaceOrInsert( EPP_Persist_Slide | nPageNum, mpStrm->Tell() );
159 mpPptEscherEx->OpenContainer( EPP_Slide );
160 mpPptEscherEx->AddAtom( 24, EPP_SlideAtom, 2 );
161 mpStrm->WriteInt32( static_cast<sal_Int32>(rLayout.nLayout) );
162 mpStrm->WriteBytes(rLayout.nPlaceHolder, 8); // placeholderIDs (8 parts)
163 mpStrm->WriteUInt32( nMasterNum | 0x80000000 ) // master ID (equals 0x80000000 on a master page)
164 .WriteUInt32( nPageNum + 0x100 ) // notes ID (equals null if no notes are present)
165 .WriteUInt16( nMode )
166 .WriteUInt16( 0 ); // padword
167
168 mnDiaMode = 0;
169 bool bVisible = true;
170 css::presentation::FadeEffect eFe = css::presentation::FadeEffect_NONE;
171
172 if ( GetPropertyValue( aAny, mXPagePropSet, "Visible" ) )
173 aAny >>= bVisible;
174 if ( GetPropertyValue( aAny, mXPagePropSet, "Change" ) )
175 {
176 switch ( *o3tl::doAccess<sal_Int32>(aAny) )
177 {
178 case 1 : // automatic
179 mnDiaMode++;
180 [[fallthrough]];
181 case 2 : // semi-automatic
182 mnDiaMode++;
183 break;
184 default :
185 case 0 : // manual
186 break;
187 }
188 }
189 if ( GetPropertyValue( aAny, mXPagePropSet, "Effect" ) )
190 aAny >>= eFe;
191
192 sal_uInt32 nSoundRef = 0;
193 bool bIsSound = false;
194 bool bStopSound = false;
195 bool bLoopSound = false;
196
197 if ( GetPropertyValue( aAny, mXPagePropSet, "Sound" ) )
198 {
199 OUString aSoundURL;
200 if ( aAny >>= aSoundURL )
201 {
202 nSoundRef = maSoundCollection.GetId( aSoundURL );
203 bIsSound = true;
204 }
205 else
206 aAny >>= bStopSound;
207 }
208 if ( GetPropertyValue( aAny, mXPagePropSet, "LoopSound" ) )
209 aAny >>= bLoopSound;
210
211 bool bNeedsSSSlideInfoAtom = !bVisible
212 || ( mnDiaMode == 2 )
213 || bIsSound
214 || bStopSound
215 || ( eFe != css::presentation::FadeEffect_NONE );
216 if ( bNeedsSSSlideInfoAtom )
217 {
218 sal_uInt8 nDirection = 0;
219 sal_uInt8 nTransitionType = 0;
220 sal_uInt16 nBuildFlags = 1; // advance by mouseclick
221 sal_Int32 nSlideTime = 0; // still has to !!!
222 sal_uInt8 nSpeed = 1;
223
224 if ( GetPropertyValue( aAny, mXPagePropSet, "TransitionDuration" ) )
225 {
226 css::presentation::AnimationSpeed aAs;
227 double fTransitionDuration = -1.0;
228 aAny >>= fTransitionDuration;
229
230 if (fTransitionDuration >= 0)
231 {
232 if (fTransitionDuration <= 0.5)
233 {
234 aAs = css::presentation::AnimationSpeed::AnimationSpeed_FAST;
235 }
236 else if (fTransitionDuration >= 1.0)
237 {
238 aAs = css::presentation::AnimationSpeed::AnimationSpeed_SLOW;
239 }
240 else
241 {
242 aAs = css::presentation::AnimationSpeed::AnimationSpeed_MEDIUM;
243 }
244 }
245 else
246 aAs = css::presentation::AnimationSpeed::AnimationSpeed_MEDIUM;
247
248 nSpeed = static_cast<sal_uInt8>(aAs);
249 }
250 sal_Int16 nTT = 0;
251 if ( GetPropertyValue( aAny, mXPagePropSet, "TransitionType" )
252 && ( aAny >>= nTT ) )
253 {
254 sal_Int16 nTST = 0;
255 if ( GetPropertyValue( aAny, mXPagePropSet, "TransitionSubtype" )
256 && ( aAny >>= nTST ) )
257 nTransitionType = GetTransition( nTT, nTST, eFe, 0, nDirection );
258
259 }
260 if ( !nTransitionType )
261 nTransitionType = GetTransition( eFe, nDirection );
262 if ( mnDiaMode == 2 ) // automatic ?
263 nBuildFlags |= 0x400;
264 if ( !bVisible )
265 nBuildFlags |= 4;
266 if ( bIsSound )
267 nBuildFlags |= 16;
268 if ( bLoopSound )
269 nBuildFlags |= 64;
270 if ( bStopSound )
271 nBuildFlags |= 256;
272
273 if ( GetPropertyValue( aAny, mXPagePropSet, "Duration" ) )// duration of this slide
274 nSlideTime = *o3tl::doAccess<sal_Int32>(aAny) << 10; // in ticks
275
276 mpPptEscherEx->AddAtom( 16, EPP_SSSlideInfoAtom );
277 mpStrm->WriteInt32( nSlideTime ) // standtime in ticks
278 .WriteUInt32( nSoundRef )
279 .WriteUChar( nDirection )
280 .WriteUChar( nTransitionType )
281 .WriteUInt16( nBuildFlags )
282 .WriteUChar( nSpeed )
283 .WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 );
284 }
285
286 ImplCreateHeaderFooters( mXPagePropSet );
287
288 EscherSolverContainer aSolverContainer;
289 mpPptEscherEx->OpenContainer( EPP_PPDrawing );
290 mpPptEscherEx->OpenContainer( ESCHER_DgContainer );
291 mpPptEscherEx->EnterGroup(nullptr,nullptr);
292 ImplWritePage( rLayout, aSolverContainer, NORMAL, false, nPageNum ); // the shapes of the pages are created in the PPT document
293 mpPptEscherEx->LeaveGroup();
294
295 if ( bHasBackground )
296 ImplWriteBackground( aXBackgroundPropSet );
297 else
298 {
299 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
300 mpPptEscherEx->AddShape( ESCHER_ShpInst_Rectangle,
301 ShapeFlag::Background | ShapeFlag::HaveShapeProperty );
302 EscherPropertyContainer aPropOpt;
303 aPropOpt.AddOpt( ESCHER_Prop_fillRectRight, PPTtoEMU( maDestPageSize.Width ) );
304 aPropOpt.AddOpt( ESCHER_Prop_fillRectBottom, PPTtoEMU( maDestPageSize.Width ) );
305 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x120012 );
306 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
307 aPropOpt.AddOpt( ESCHER_Prop_bWMode, ESCHER_wDontShow );
308 aPropOpt.AddOpt( ESCHER_Prop_fBackground, 0x10001 ); // if true, this is the background shape
309 aPropOpt.Commit( *mpStrm );
310 mpPptEscherEx->CloseContainer(); // ESCHER_SpContainer
311 }
312
313 aSolverContainer.WriteSolver( *mpStrm );
314
315 mpPptEscherEx->CloseContainer(); // ESCHER_DgContainer
316 mpPptEscherEx->CloseContainer(); // EPP_Drawing
317 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 1 );
318 mpStrm->WriteUInt32( 0xffffff ).WriteUInt32( 0x000000 ).WriteUInt32( 0x808080 ).WriteUInt32( 0x000000 ).WriteUInt32( 0x99cc00 ).WriteUInt32( 0xcc3333 ).WriteUInt32( 0xffcccc ).WriteUInt32( 0xb2b2b2 );
319
320 SvMemoryStream aBinaryTagData10Atom;
321 ImplExportComments( mXDrawPage, aBinaryTagData10Atom );
322 SvMemoryStream amsofbtAnimGroup;
323 ppt::AnimationExporter aExporter( aSolverContainer, maSoundCollection );
324 aExporter.doexport( mXDrawPage, amsofbtAnimGroup );
325 sal_uInt32 nmsofbtAnimGroupSize = amsofbtAnimGroup.Tell();
326 if ( nmsofbtAnimGroupSize )
327 {
328 {
329 EscherExAtom aMagic2( aBinaryTagData10Atom, 0x2eeb );
330 aBinaryTagData10Atom.WriteUInt32( 0x01c45df9 )
331 .WriteUInt32( 0xe1471b30 );
332 }
333 {
334 EscherExAtom aMagic( aBinaryTagData10Atom, 0x2b00 );
335 aBinaryTagData10Atom.WriteUInt32( 0 );
336 }
337 aBinaryTagData10Atom.WriteBytes(amsofbtAnimGroup.GetData(), amsofbtAnimGroup.Tell());
338 {
339 EscherExContainer aMagic2( aBinaryTagData10Atom, 0x2b02 );
340 }
341 }
342 if ( aBinaryTagData10Atom.Tell() )
343 {
344 EscherExContainer aProgTags ( *mpStrm, EPP_ProgTags );
345 EscherExContainer aProgBinaryTag( *mpStrm, EPP_ProgBinaryTag );
346 {
347 EscherExAtom aCString( *mpStrm, EPP_CString );
348 mpStrm->WriteUInt32( 0x5f005f )
349 .WriteUInt32( 0x50005f )
350 .WriteUInt32( 0x540050 )
351 .WriteUInt16( 0x31 )
352 .WriteUInt16( 0x30 );
353 }
354 {
355 EscherExAtom aBinaryTagData( *mpStrm, EPP_BinaryTagData );
356 mpStrm->WriteBytes(aBinaryTagData10Atom.GetData(), aBinaryTagData10Atom.Tell());
357 }
358 }
359 mpPptEscherEx->CloseContainer(); // EPP_Slide
360 }
361
ImplWriteSlideMaster(sal_uInt32 nPageNum,Reference<XPropertySet> const & aXBackgroundPropSet)362 void PPTWriter::ImplWriteSlideMaster( sal_uInt32 nPageNum, Reference< XPropertySet > const & aXBackgroundPropSet )
363 {
364 if (!aXBackgroundPropSet)
365 return;
366 mpPptEscherEx->PtReplaceOrInsert( EPP_Persist_MainMaster | nPageNum, mpStrm->Tell() );
367 mpPptEscherEx->OpenContainer( EPP_MainMaster );
368 mpPptEscherEx->AddAtom( 24, EPP_SlideAtom, 2 );
369 mpStrm->WriteInt32( static_cast<sal_Int32>(EppLayout::TITLEANDBODYSLIDE) ) // slide layout -> title and body slide
370 .WriteUChar( 1 ).WriteUChar( 2 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ).WriteUChar( 0 ) // placeholderID
371 .WriteUInt32( 0 ) // master ID (equals null at a master page)
372 .WriteUInt32( 0 ) // notes ID (equals null if no notes are present)
373 .WriteUInt16( 0 ) // Bit 1: Follow master objects, Bit 2: Follow master scheme, Bit 3: Follow master background
374 .WriteUInt16( 0 ); // padword
375
376 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 6 );
377 mpStrm->WriteUInt32( 0xffffff ).WriteUInt32( 0x000000 ).WriteUInt32( 0x808080 ).WriteUInt32( 0x000000 ).WriteUInt32( 0x99cc00 ).WriteUInt32( 0xcc3333 ).WriteUInt32( 0xffcccc ).WriteUInt32( 0xb2b2b2 );
378 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 6 );
379 mpStrm->WriteUInt32( 0xff0000 ).WriteUInt32( 0xffffff ).WriteUInt32( 0x000000 ).WriteUInt32( 0x00ffff ).WriteUInt32( 0x0099ff ).WriteUInt32( 0xffff00 ).WriteUInt32( 0x0000ff ).WriteUInt32( 0x969696 );
380 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 6 );
381 mpStrm->WriteUInt32( 0xccffff ).WriteUInt32( 0x000000 ).WriteUInt32( 0x336666 ).WriteUInt32( 0x008080 ).WriteUInt32( 0x339933 ).WriteUInt32( 0x000080 ).WriteUInt32( 0xcc3300 ).WriteUInt32( 0x66ccff );
382 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 6 );
383 mpStrm->WriteUInt32( 0xffffff ).WriteUInt32( 0x000000 ).WriteUInt32( 0x333333 ).WriteUInt32( 0x000000 ).WriteUInt32( 0xdddddd ).WriteUInt32( 0x808080 ).WriteUInt32( 0x4d4d4d ).WriteUInt32( 0xeaeaea );
384 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 6 );
385 mpStrm->WriteUInt32( 0xffffff ).WriteUInt32( 0x000000 ).WriteUInt32( 0x808080 ).WriteUInt32( 0x000000 ).WriteUInt32( 0x66ccff ).WriteUInt32( 0xff0000 ).WriteUInt32( 0xcc00cc ).WriteUInt32( 0xc0c0c0 );
386 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 6 );
387 mpStrm->WriteUInt32( 0xffffff ).WriteUInt32( 0x000000 ).WriteUInt32( 0x808080 ).WriteUInt32( 0x000000 ).WriteUInt32( 0xc0c0c0 ).WriteUInt32( 0xff6600 ).WriteUInt32( 0x0000ff ).WriteUInt32( 0x009900 );
388 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 6 );
389 mpStrm->WriteUInt32( 0xffffff ).WriteUInt32( 0x000000 ).WriteUInt32( 0x808080 ).WriteUInt32( 0x000000 ).WriteUInt32( 0xff9933 ).WriteUInt32( 0xccff99 ).WriteUInt32( 0xcc00cc ).WriteUInt32( 0xb2b2b2 );
390
391 for ( int nInstance = EPP_TEXTTYPE_Title; nInstance <= EPP_TEXTTYPE_QuarterBody; nInstance++ )
392 {
393 if ( nInstance == EPP_TEXTTYPE_notUsed )
394 continue;
395
396 // the auto color is dependent to the page background,so we have to set a page that is in the right context
397 if ( nInstance == EPP_TEXTTYPE_Notes )
398 (void)GetPageByIndex(0, NOTICE);
399 else
400 (void)GetPageByIndex(0, MASTER);
401
402 mpPptEscherEx->BeginAtom();
403
404 bool bSimpleText = false;
405
406 mpStrm->WriteUInt16( 5 ); // paragraph count
407
408 for ( sal_uInt16 nLev = 0; nLev < 5; nLev++ )
409 {
410 if ( nInstance >= EPP_TEXTTYPE_CenterBody )
411 {
412 bSimpleText = true;
413 mpStrm->WriteUInt16( nLev );
414 }
415 mpStyleSheet->mpParaSheet[ nInstance ]->Write( *mpStrm, nLev, bSimpleText, mXPagePropSet );
416 mpStyleSheet->mpCharSheet[ nInstance ]->Write( *mpStrm, nLev, bSimpleText, mXPagePropSet );
417 }
418 mpPptEscherEx->EndAtom( EPP_TxMasterStyleAtom, 0, nInstance );
419 }
420 GetPageByIndex( nPageNum, MASTER );
421
422 EscherSolverContainer aSolverContainer;
423
424 mpPptEscherEx->OpenContainer( EPP_PPDrawing );
425 mpPptEscherEx->OpenContainer( ESCHER_DgContainer );
426
427 mpPptEscherEx->EnterGroup(nullptr,nullptr);
428 ImplWritePage( GetLayout( 0 ), aSolverContainer, MASTER, true ); // the shapes of the pages are created in the PPT document
429 mpPptEscherEx->LeaveGroup();
430
431 ImplWriteBackground( aXBackgroundPropSet );
432
433 aSolverContainer.WriteSolver( *mpStrm );
434
435 mpPptEscherEx->CloseContainer(); // ESCHER_DgContainer
436 mpPptEscherEx->CloseContainer(); // EPP_Drawing
437 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 1 );
438 mpStrm->WriteUInt32( 0xffffff ).WriteUInt32( 0x000000 ).WriteUInt32( 0x808080 ).WriteUInt32( 0x000000 ).WriteUInt32( 0x99cc00 ).WriteUInt32( 0xcc3333 ).WriteUInt32( 0xffcccc ).WriteUInt32( 0xb2b2b2 );
439
440 if ( aBuExMasterStream.Tell() )
441 {
442 ImplProgTagContainer( mpStrm.get(), &aBuExMasterStream );
443 }
444 mpPptEscherEx->CloseContainer(); // EPP_MainMaster
445 };
446
~PPTWriter()447 PPTWriter::~PPTWriter()
448 {
449 mpExEmbed.reset();
450 mpPptEscherEx.reset();
451 mpCurUserStrm.clear();
452 mpPicStrm.clear();
453 mpStrm.clear();
454 maStyleSheetList.clear();
455 maExOleObj.clear();
456 if ( mbStatusIndicator )
457 mXStatusIndicator->end();
458 }
459
ImplCreateCurrentUserStream()460 bool PPTWriter::ImplCreateCurrentUserStream()
461 {
462 mpCurUserStrm = mrStg->OpenSotStream( "Current User" );
463 if ( !mpCurUserStrm )
464 return false;
465 char pUserName[] = "Current User";
466 sal_uInt32 nLenOfUserName = strlen( pUserName );
467 sal_uInt32 nSizeOfRecord = 0x14 + ( ( nLenOfUserName + 4 ) & ~ 3 );
468
469 mpCurUserStrm->WriteUInt16( 0 ).WriteUInt16( EPP_CurrentUserAtom ).WriteUInt32( nSizeOfRecord );
470 mpCurUserStrm->WriteUInt32( 0x14 ) // Len
471 .WriteUInt32( 0xe391c05f ); // Magic
472
473 sal_uInt32 nEditPos = mpCurUserStrm->Tell();
474 mpCurUserStrm->WriteUInt32( 0x0 ) // OffsetToCurrentEdit;
475 .WriteUInt16( nLenOfUserName )
476 .WriteUInt16( 0x3f4 ) // DocFileVersion
477 .WriteUChar( 3 ) // MajorVersion
478 .WriteUChar( 0 ) // MinorVersion
479 .WriteUInt16( 0 ); // Pad Word
480 pUserName[ nLenOfUserName ] = 8;
481 mpCurUserStrm->WriteBytes(pUserName, nLenOfUserName + 1);
482 for ( sal_uInt32 i = 0x15 + nLenOfUserName; i < nSizeOfRecord; i++ )
483 {
484 mpCurUserStrm->WriteUChar( 0 ); // pad bytes
485 }
486 mpCurUserStrm->Seek( nEditPos );
487 return true;
488 };
489
ImplCreateDocumentSummaryInformation()490 void PPTWriter::ImplCreateDocumentSummaryInformation()
491 {
492 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
493 mXModel, uno::UNO_QUERY_THROW);
494 uno::Reference<document::XDocumentProperties> xDocProps(
495 xDPS->getDocumentProperties());
496
497 if (!xDocProps.is())
498 return;
499
500 // no idea what this is...
501 static const sal_Int8 aGuid[ 0x52 ] =
502 {
503 0x4e, 0x00, 0x00, 0x00,
504 '{',0,'D',0,'B',0,'1',0,'A',0,'C',0,'9',0,'6',0,'4',0,'-',0,
505 'E',0,'3',0,'9',0,'C',0,'-',0,'1',0,'1',0,'D',0,'2',0,'-',0,
506 'A',0,'1',0,'E',0,'F',0,'-',0,'0',0,'0',0,'6',0,'0',0,'9',0,
507 '7',0,'D',0,'A',0,'5',0,'6',0,'8',0,'9',0,'}',0
508 };
509 uno::Sequence<sal_Int8> aGuidSeq(aGuid, 0x52);
510
511 SvMemoryStream aHyperBlob;
512 ImplCreateHyperBlob( aHyperBlob );
513
514 auto nHyperLength = static_cast<sal_Int32>(aHyperBlob.Tell());
515 const sal_Int8* pBlob(
516 static_cast<const sal_Int8*>(aHyperBlob.GetData()));
517 auto aHyperSeq = comphelper::arrayToSequence<sal_Int8>(pBlob, nHyperLength);
518
519 if ( mnCnvrtFlags & 0x8000 )
520 {
521 uno::Sequence<sal_Int8> aThumbSeq;
522 if ( GetPageByIndex( 0, NORMAL ) && ImplGetPropertyValue( mXPagePropSet, "PreviewBitmap" ) )
523 {
524 aThumbSeq = *o3tl::doAccess<uno::Sequence<sal_Int8>>(mAny);
525 }
526 sfx2::SaveOlePropertySet( xDocProps, mrStg.get(),
527 &aThumbSeq, &aGuidSeq, &aHyperSeq);
528 }
529 else
530 {
531 sfx2::SaveOlePropertySet( xDocProps, mrStg.get(),
532 nullptr, &aGuidSeq, &aHyperSeq );
533 }
534 }
535
ImplWriteExtParaHeader(SvMemoryStream & rSt,sal_uInt32 nRef,sal_uInt32 nInstance,sal_uInt32 nSlideId)536 void PPTWriter::ImplWriteExtParaHeader( SvMemoryStream& rSt, sal_uInt32 nRef, sal_uInt32 nInstance, sal_uInt32 nSlideId )
537 {
538 if ( rSt.Tell() )
539 {
540 aBuExOutlineStream.WriteUInt32( ( EPP_PST_ExtendedParagraphHeaderAtom << 16 )
541 | ( nRef << 4 ) )
542 .WriteUInt32( 8 )
543 .WriteUInt32( nSlideId )
544 .WriteUInt32( nInstance );
545 aBuExOutlineStream.WriteBytes(rSt.GetData(), rSt.Tell());
546 }
547 }
548
ImplCreateHeaderFooterStrings(SvStream & rStrm,css::uno::Reference<css::beans::XPropertySet> const & rXPagePropSet)549 void PPTWriter::ImplCreateHeaderFooterStrings( SvStream& rStrm, css::uno::Reference< css::beans::XPropertySet > const & rXPagePropSet )
550 {
551 if ( !rXPagePropSet.is() )
552 return;
553
554 OUString aString;
555 css::uno::Any aAny;
556 if ( PropValue::GetPropertyValue( aAny, rXPagePropSet, "HeaderText", true ) )
557 {
558 if ( aAny >>= aString )
559 PPTWriter::WriteCString( rStrm, aString, 1 );
560 }
561 if ( PropValue::GetPropertyValue( aAny, rXPagePropSet, "FooterText", true ) )
562 {
563 if ( aAny >>= aString )
564 PPTWriter::WriteCString( rStrm, aString, 2 );
565 }
566 if ( PropValue::GetPropertyValue( aAny, rXPagePropSet, "DateTimeText", true ) )
567 {
568 if ( aAny >>= aString )
569 PPTWriter::WriteCString( rStrm, aString );
570 }
571 }
572
ImplCreateHeaderFooters(css::uno::Reference<css::beans::XPropertySet> const & rXPagePropSet)573 void PPTWriter::ImplCreateHeaderFooters( css::uno::Reference< css::beans::XPropertySet > const & rXPagePropSet )
574 {
575 if ( !rXPagePropSet.is() )
576 return;
577
578 bool bVal = false;
579 sal_uInt32 nVal = 0;
580 css::uno::Any aAny;
581 if ( PropValue::GetPropertyValue( aAny, rXPagePropSet, "IsHeaderVisible", true ) )
582 {
583 if ( ( aAny >>= bVal ) && bVal )
584 nVal |= 0x100000;
585 }
586 if ( PropValue::GetPropertyValue( aAny, rXPagePropSet, "IsFooterVisible", true ) )
587 {
588 if ( ( aAny >>= bVal ) && bVal )
589 nVal |= 0x200000;
590 }
591 if ( PropValue::GetPropertyValue( aAny, rXPagePropSet, "IsDateTimeVisible", true ) )
592 {
593 if ( ( aAny >>= bVal ) && bVal )
594 nVal |= 0x010000;
595 }
596 if ( PropValue::GetPropertyValue( aAny, rXPagePropSet, "IsPageNumberVisible", true ) )
597 {
598 if ( ( aAny >>= bVal ) && bVal )
599 nVal |= 0x080000;
600 }
601 if ( PropValue::GetPropertyValue( aAny, rXPagePropSet, "IsDateTimeFixed", true ) )
602 {
603 if ( ( aAny >>= bVal ) && !bVal )
604 nVal |= 0x20000;
605 else
606 nVal |= 0x40000;
607 }
608 if ( PropValue::GetPropertyValue( aAny, rXPagePropSet, "DateTimeFormat", true ) )
609 {
610 sal_Int32 nFormat = *o3tl::doAccess<sal_Int32>(aAny);
611 SvxDateFormat eDateFormat = static_cast<SvxDateFormat>( nFormat & 0xf );
612 SvxTimeFormat eTimeFormat = static_cast<SvxTimeFormat>( ( nFormat >> 4 ) & 0xf );
613 switch( eDateFormat )
614 {
615 case SvxDateFormat::F :
616 nFormat = 1;
617 break;
618 case SvxDateFormat::D :
619 nFormat = 2;
620 break;
621 case SvxDateFormat::C :
622 nFormat = 4;
623 break;
624 default:
625 case SvxDateFormat::A :
626 nFormat = 0;
627 }
628 switch( eTimeFormat )
629 {
630 case SvxTimeFormat::HH24_MM :
631 nFormat = 9;
632 break;
633 case SvxTimeFormat::HH12_MM :
634 nFormat = 11;
635 break;
636 case SvxTimeFormat::HH24_MM_SS :
637 nFormat = 10;
638 break;
639 case SvxTimeFormat::HH12_MM_SS :
640 nFormat = 12;
641 break;
642 default:
643 break;
644 }
645 nVal |= nFormat;
646 }
647
648 mpPptEscherEx->OpenContainer( EPP_HeadersFooters );
649 mpPptEscherEx->AddAtom( 4, EPP_HeadersFootersAtom );
650 mpStrm->WriteUInt32( nVal );
651 ImplCreateHeaderFooterStrings( *mpStrm, rXPagePropSet );
652 mpPptEscherEx->CloseContainer();
653 }
654
ImplCreateDocument()655 bool PPTWriter::ImplCreateDocument()
656 {
657 sal_uInt32 i;
658 sal_uInt16 nSlideType = EPP_SLIDESIZE_TYPECUSTOM;
659
660 sal_uInt32 nWidth = maDestPageSize.Width;
661 sal_uInt32 nHeight = maDestPageSize.Height;
662
663 if ( ( nWidth == 0x1680 ) && ( nHeight == 0x10e0 ) )
664 nSlideType = EPP_SLIDESIZE_TYPEONSCREEN;
665 else if ( ( nWidth == 0x1200 ) && ( nHeight == 0x240 ) )
666 nSlideType = EPP_SLIDESIZE_TYPEBANNER;
667 else if ( ( nWidth == 0x1950 ) && ( nHeight == 0x10e0 ) )
668 nSlideType = EPP_SLIDESIZE_TYPE35MM;
669 else if ( ( nWidth == 0x1860 ) && ( nHeight == 0x10e0 ) )
670 nSlideType = EPP_SLIDESIZE_TYPEA4PAPER;
671
672 mpPptEscherEx->OpenContainer( EPP_Document );
673 // CREATE DOCUMENT ATOM
674 mpPptEscherEx->AddAtom( 40, EPP_DocumentAtom, 1 );
675 mpStrm->WriteUInt32( nWidth ) // Slide Size in Master coordinates X
676 .WriteUInt32( nHeight ) // " " " " " Y
677 .WriteInt32( maNotesPageSize.Width ) // Notes Page Size X
678 .WriteInt32( maNotesPageSize.Height ) // " " " Y
679 .WriteInt32( 1 ).WriteInt32( 2 ); // the scale used when the Powerpoint document is embedded. the default is 1:2
680 mpPptEscherEx->InsertPersistOffset( EPP_MAINNOTESMASTER_PERSIST_KEY, mpStrm->Tell() );
681 mpStrm->WriteUInt32( 0 ) // Reference to NotesMaster ( 0 if none );
682 .WriteUInt32( 0 ) // Reference to HandoutMaster ( 0 if none );
683 .WriteInt16( 1 ) // Number of the first slide;
684 .WriteUInt16( nSlideType ) // Size of the document slides ( default: EPP_SLIDESIZETYPEONSCREEN )
685 .WriteUChar( 0 ) // bool1 indicates if document was saved with embedded true type fonts
686 .WriteUChar( 0 ) // bool1 indicates if the placeholders on the title slide are omitted
687 .WriteUChar( 0 ) // bool1 right to left ( flag for Bidi version )
688 .WriteUChar( 1 ); // bool1 visibility of comments shapes
689
690 mpPptEscherEx->PtInsert( EPP_Persist_Document, mpStrm->Tell() );
691
692 mpPptEscherEx->OpenContainer( EPP_HeadersFooters, 3 ); //Master footer (default)
693 mpPptEscherEx->AddAtom( 4, EPP_HeadersFootersAtom );
694 mpStrm->WriteUInt32( 0x25000d );
695 if ( GetPageByIndex( 0, MASTER ) )
696 ImplCreateHeaderFooterStrings( *mpStrm, mXPagePropSet );
697 mpPptEscherEx->CloseContainer();
698 mpPptEscherEx->OpenContainer( EPP_HeadersFooters, 4 ); //NotesMaster footer (default)
699 mpPptEscherEx->AddAtom( 4, EPP_HeadersFootersAtom );
700 mpStrm->WriteUInt32( 0x3d000d );
701 if ( GetPageByIndex( 0, NOTICE ) )
702 ImplCreateHeaderFooterStrings( *mpStrm, mXPagePropSet );
703 mpPptEscherEx->CloseContainer();
704
705 mpPptEscherEx->OpenContainer( EPP_SlideListWithText ); // animation information for the slides
706
707 for ( i = 0; i < mnPages; i++ )
708 {
709 mpPptEscherEx->AddAtom( 20, EPP_SlidePersistAtom );
710 mpPptEscherEx->InsertPersistOffset( EPP_MAINSLIDE_PERSIST_KEY | i, mpStrm->Tell() );
711 mpStrm->WriteUInt32( 0 ) // psrReference - logical reference to the slide persist object ( EPP_MAINSLIDE_PERSIST_KEY )
712 .WriteUInt32( 4 ) // flags - only bit 3 used, if set then slide contains shapes other than placeholders
713 .WriteInt32( 0 ) // numberTexts - number of placeholder texts stored with the persist object. Allows to display outline view without loading the slide persist objects
714 .WriteInt32( i + 0x100 ) // slideId - Unique slide identifier, used for OLE link monikers for example
715 .WriteUInt32( 0 ); // reserved, usually 0
716
717 if ( !GetPageByIndex( i, NORMAL ) ) // very exciting: once again through all pages
718 return false;
719 SetCurrentStyleSheet( GetMasterIndex( NORMAL ) );
720
721 css::uno::Reference< css::container::XNamed >
722 aXName( mXDrawPage, css::uno::UNO_QUERY );
723
724 if ( aXName.is() )
725 maSlideNameList.push_back( aXName->getName() );
726 else
727 maSlideNameList.emplace_back( );
728 }
729 mpPptEscherEx->CloseContainer(); // EPP_SlideListWithText
730
731 mpPptEscherEx->OpenContainer( EPP_SlideListWithText, 2 ); // animation information for the notes
732 for( i = 0; i < mnPages; i++ )
733 {
734 mpPptEscherEx->AddAtom( 20, EPP_SlidePersistAtom );
735 mpPptEscherEx->InsertPersistOffset( EPP_MAINNOTES_PERSIST_KEY | i, mpStrm->Tell() );
736 mpStrm->WriteUInt32( 0 )
737 .WriteUInt32( 4 )
738 .WriteInt32( 0 )
739 .WriteInt32( i + 0x100 )
740 .WriteUInt32( 0 );
741 }
742 mpPptEscherEx->CloseContainer(); // EPP_SlideListWithText
743
744 css::uno::Reference< css::presentation::XPresentationSupplier >
745 aXPresSupplier( mXModel, css::uno::UNO_QUERY );
746 if ( aXPresSupplier.is() )
747 {
748 css::uno::Reference< css::presentation::XPresentation > aXPresentation( aXPresSupplier->getPresentation() );
749 if ( aXPresentation.is() )
750 {
751 mXPropSet.set( aXPresentation, css::uno::UNO_QUERY );
752 if ( mXPropSet.is() )
753 {
754 OUString aCustomShow;
755 sal_uInt32 const nPenColor = 0x1000000;
756 sal_Int32 const nRestartTime = 0x7fffffff;
757 sal_Int16 nStartSlide = 0;
758 sal_Int16 nEndSlide = 0;
759 sal_uInt32 nFlags = 0; // Bit 0: Auto advance
760 // Bit 1 Skip builds ( do not allow slide effects )
761 // Bit 2 Use slide range
762 // Bit 3 Use named show
763 // Bit 4 Browse mode on
764 // Bit 5 Kiosk mode on
765 // Bit 6 Skip narration
766 // Bit 7 loop continuously
767 // Bit 8 show scrollbar
768
769 if ( ImplGetPropertyValue( "CustomShow" ) )
770 {
771 aCustomShow = *o3tl::doAccess<OUString>(mAny);
772 if ( !aCustomShow.isEmpty() )
773 {
774 nFlags |= 8;
775 }
776 }
777 if ( ( nFlags & 8 ) == 0 )
778 {
779 if ( ImplGetPropertyValue( "FirstPage" ) )
780 {
781 auto aSlideName = o3tl::doAccess<OUString>(mAny);
782
783 std::vector<OUString>::const_iterator pIter = std::find(
784 maSlideNameList.begin(),maSlideNameList.end(), *aSlideName);
785
786 if (pIter != maSlideNameList.end())
787 {
788 nStartSlide = pIter - maSlideNameList.begin() + 1;
789 nFlags |= 4;
790 nEndSlide = static_cast<sal_uInt16>(mnPages);
791 }
792 }
793 }
794
795 if ( ImplGetPropertyValue( "IsAutomatic" ) )
796 {
797 bool bBool = false;
798 mAny >>= bBool;
799 if ( !bBool )
800 nFlags |= 1;
801 }
802
803 if ( ImplGetPropertyValue( "IsEndless" ) )
804 {
805 bool bBool = false;
806 mAny >>= bBool;
807 if ( bBool )
808 nFlags |= 0x80;
809 }
810 if ( ImplGetPropertyValue( "IsFullScreen" ) )
811 {
812 bool bBool = false;
813 mAny >>= bBool;
814 if ( !bBool )
815 nFlags |= 0x11;
816 }
817
818 mpPptEscherEx->AddAtom( 80, EPP_SSDocInfoAtom, 1 );
819 mpStrm->WriteUInt32( nPenColor ).WriteInt32( nRestartTime ).WriteInt16( nStartSlide ).WriteInt16( nEndSlide );
820
821 sal_uInt32 nCustomShowNameLen = aCustomShow.getLength();
822 if ( nCustomShowNameLen > 31 )
823 nCustomShowNameLen = 31;
824 if ( nCustomShowNameLen ) // named show identifier
825 {
826 const sal_Unicode* pCustomShow = aCustomShow.getStr();
827 for ( i = 0; i < nCustomShowNameLen; i++ )
828 {
829 mpStrm->WriteUInt16( pCustomShow[ i ] );
830 }
831 }
832 for ( i = nCustomShowNameLen; i < 32; i++, mpStrm->WriteUInt16( 0 ) ) ;
833
834 mpStrm->WriteUInt32( nFlags );
835 css::uno::Reference< css::presentation::XCustomPresentationSupplier > aXCPSup( mXModel, css::uno::UNO_QUERY );
836 if ( aXCPSup.is() )
837 {
838 css::uno::Reference< css::container::XNameContainer > aXCont( aXCPSup->getCustomPresentations() );
839 if ( aXCont.is() )
840 {
841 const css::uno::Sequence< OUString> aNameSeq( aXCont->getElementNames() );
842 if ( aNameSeq.hasElements() )
843 {
844 mpPptEscherEx->OpenContainer( EPP_NamedShows );
845 sal_uInt32 nCustomShowIndex = 0;
846 for( OUString const & customShowName : aNameSeq )
847 {
848 if ( !customShowName.isEmpty() )
849 {
850 mpPptEscherEx->OpenContainer( EPP_NamedShow, nCustomShowIndex++ );
851
852 sal_uInt32 nNamedShowLen = customShowName.getLength();
853 if ( nNamedShowLen > 31 )
854 nNamedShowLen = 31;
855 mpPptEscherEx->AddAtom( nNamedShowLen << 1, EPP_CString );
856 const sal_Unicode* pCustomShowName = customShowName.getStr();
857 for ( sal_uInt32 k = 0; k < nNamedShowLen; ++k )
858 mpStrm->WriteUInt16( pCustomShowName[ k ] );
859 mAny = aXCont->getByName( customShowName );
860 css::uno::Reference< css::container::XIndexContainer > aXIC;
861 if ( mAny >>= aXIC )
862 {
863 mpPptEscherEx->BeginAtom();
864
865 sal_Int32 nSlideCount = aXIC->getCount();
866 for ( sal_Int32 j = 0; j < nSlideCount; j++ ) // number of slides
867 {
868 mAny = aXIC->getByIndex( j );
869 css::uno::Reference< css::drawing::XDrawPage > aXDrawPage;
870 if ( mAny >>= aXDrawPage )
871 {
872 css::uno::Reference< css::container::XNamed > aXName( aXDrawPage, css::uno::UNO_QUERY );
873 if ( aXName.is() )
874 {
875 OUString aSlideName( aXName->getName() );
876 std::vector<OUString>::const_iterator pIter = std::find(
877 maSlideNameList.begin(),maSlideNameList.end(),aSlideName);
878
879 if (pIter != maSlideNameList.end())
880 {
881 sal_uInt32 nPageNumber = pIter - maSlideNameList.begin();
882 mpStrm->WriteUInt32( nPageNumber + 0x100 ); // unique slide id
883 }
884 }
885 }
886 }
887 mpPptEscherEx->EndAtom( EPP_NamedShowSlides );
888 }
889 mpPptEscherEx->CloseContainer(); // EPP_NamedShow
890 }
891 }
892 mpPptEscherEx->CloseContainer(); // EPP_NamedShows
893 }
894 }
895 }
896 }
897 }
898 }
899 mpPptEscherEx->AddAtom( 0, EPP_EndDocument );
900 mpPptEscherEx->CloseContainer(); // EPP_Document
901 return true;
902 };
903
ImplCreateHyperBlob(SvMemoryStream & rStrm)904 void PPTWriter::ImplCreateHyperBlob( SvMemoryStream& rStrm )
905 {
906 sal_uInt32 nCurrentOfs, nParaOfs, nParaCount = 0;
907
908 nParaOfs = rStrm.Tell();
909 rStrm.WriteUInt32( 0 ); // property size
910 rStrm.WriteUInt32( 0 ); // property count
911
912 for ( const auto& rHyperlink : maHyperlink )
913 {
914 nParaCount += 6;
915 rStrm .WriteUInt32( 3 ) // Type VT_I4
916 .WriteUInt32( 7 ) // (VTI4 - Private1)
917 .WriteUInt32( 3 ) // Type VT_I4
918 .WriteUInt32( 6 ) // (VTI4 - Private2)
919 .WriteUInt32( 3 ) // Type VT_I4
920 .WriteUInt32( 0 ); // (VTI4 - Private3)
921
922 // INFO
923 // HIWORD: = 0 : do not change anything
924 // = 1 : replace the hyperlink with the target and subaddress in the following two VTLPWSTR
925 // = 2 : delete the hyperlink
926 // LOWORD: = 0 : graphic shown as background (link)
927 // = 1 : graphic shown as shape (link)
928 // = 2 : graphic is used to fill a shape
929 // = 3 : graphic used to fill a shape outline (future use)
930 // = 4 : hyperlink attached to a shape
931 // = 5 : " " " " (Word) field
932 // = 6 : " " " " (Excel) range
933 // = 7 : " " " " (PPT) text range
934 // = 8 : " " " " (Project) task
935
936 sal_Int32 nUrlLen = rHyperlink.aURL.getLength();
937 const OUString& rUrl = rHyperlink.aURL;
938
939 sal_uInt32 const nInfo = 7;
940
941 rStrm .WriteUInt32( 3 ) // Type VT_I4
942 .WriteUInt32( nInfo ); // Info
943
944 switch( rHyperlink.nType & 0xff )
945 {
946 case 1 : // click action to slidenumber
947 {
948 rStrm.WriteUInt32( 0x1f ).WriteUInt32( 1 ).WriteUInt32( 0 ); // path
949 rStrm.WriteUInt32( 0x1f ).WriteUInt32( nUrlLen + 1 );
950 for ( sal_Int32 i = 0; i < nUrlLen; i++ )
951 {
952 rStrm.WriteUInt16( rUrl[ i ] );
953 }
954 rStrm.WriteUInt16( 0 );
955 }
956 break;
957 case 2 :
958 {
959 sal_Int32 i;
960
961 rStrm .WriteUInt32( 0x1f )
962 .WriteUInt32( nUrlLen + 1 );
963 for ( i = 0; i < nUrlLen; i++ )
964 {
965 rStrm.WriteUInt16( rUrl[ i ] );
966 }
967 if ( ! ( i & 1 ) )
968 rStrm.WriteUInt16( 0 );
969 rStrm .WriteUInt16( 0 )
970 .WriteUInt32( 0x1f )
971 .WriteUInt32( 1 )
972 .WriteUInt32( 0 );
973 }
974 break;
975 }
976 }
977 nCurrentOfs = rStrm.Tell();
978 rStrm.Seek( nParaOfs );
979 rStrm.WriteUInt32( nCurrentOfs - ( nParaOfs + 4 ) );
980 rStrm.WriteUInt32( nParaCount );
981 rStrm.Seek( nCurrentOfs );
982 }
983
ImplCreateMainNotes()984 bool PPTWriter::ImplCreateMainNotes()
985 {
986 EscherSolverContainer aSolverContainer;
987
988 mpPptEscherEx->PtReplaceOrInsert( EPP_Persist_MainNotes, mpStrm->Tell() );
989 mpPptEscherEx->OpenContainer( EPP_Notes );
990 mpPptEscherEx->AddAtom( 8, EPP_NotesAtom, 1 );
991 mpStrm->WriteUInt32( 0x80000001 ) // Number that identifies this slide
992 .WriteUInt32( 0 ); // follow nothing
993 mpPptEscherEx->OpenContainer( EPP_PPDrawing );
994 mpPptEscherEx->OpenContainer( ESCHER_DgContainer );
995 mpPptEscherEx->EnterGroup(nullptr,nullptr);
996
997 ImplWritePage( GetLayout( 20 ), aSolverContainer, NOTICE, true );
998
999 mpPptEscherEx->LeaveGroup();
1000 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
1001 mpPptEscherEx->AddShape( ESCHER_ShpInst_Rectangle, ShapeFlag::Background | ShapeFlag::HaveShapeProperty );
1002 EscherPropertyContainer aPropOpt;
1003 aPropOpt.AddOpt( ESCHER_Prop_fillColor, 0xffffff ); // stock valued fill color
1004 aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0 );
1005 aPropOpt.AddOpt( ESCHER_Prop_fillRectRight, 0x68bdde );
1006 aPropOpt.AddOpt( ESCHER_Prop_fillRectBottom, 0x8b9f8e );
1007 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x120012 );
1008 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0 );
1009 aPropOpt.AddOpt( ESCHER_Prop_bWMode, ESCHER_wDontShow );
1010 aPropOpt.AddOpt( ESCHER_Prop_fBackground, 0x10001 ); // if true, this is the background shape
1011 aPropOpt.Commit( *mpStrm );
1012 mpPptEscherEx->CloseContainer(); // ESCHER_SpContainer
1013
1014 aSolverContainer.WriteSolver( *mpStrm );
1015
1016 mpPptEscherEx->CloseContainer(); // ESCHER_DgContainer
1017 mpPptEscherEx->CloseContainer(); // EPP_Drawing
1018 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 1 );
1019 mpStrm->WriteUInt32( 0xffffff ).WriteUInt32( 0x000000 ).WriteUInt32( 0x808080 ).WriteUInt32( 0x000000 ).WriteUInt32( 0x99cc00 ).WriteUInt32( 0xcc3333 ).WriteUInt32( 0xffcccc ).WriteUInt32( 0xb2b2b2 );
1020 mpPptEscherEx->CloseContainer(); // EPP_Notes
1021 return true;
1022 }
1023
getInitials(const OUString & rName)1024 static OUString getInitials( const OUString& rName )
1025 {
1026 OUStringBuffer sInitials;
1027
1028 const sal_Unicode * pStr = rName.getStr();
1029 sal_Int32 nLength = rName.getLength();
1030
1031 while( nLength )
1032 {
1033 // skip whitespace
1034 while( nLength && (*pStr <= ' ') )
1035 {
1036 nLength--; pStr++;
1037 }
1038
1039 // take letter
1040 if( nLength )
1041 {
1042 sInitials.append( *pStr );
1043 nLength--; pStr++;
1044 }
1045
1046 // skip letters until whitespace
1047 while( nLength && (*pStr > ' ') )
1048 {
1049 nLength--; pStr++;
1050 }
1051 }
1052
1053 return sInitials.makeStringAndClear();
1054 }
1055
ImplExportComments(const uno::Reference<drawing::XDrawPage> & xPage,SvMemoryStream & rBinaryTagData10Atom)1056 void ImplExportComments( const uno::Reference< drawing::XDrawPage >& xPage, SvMemoryStream& rBinaryTagData10Atom )
1057 {
1058 try
1059 {
1060 uno::Reference< office::XAnnotationAccess > xAnnotationAccess( xPage, uno::UNO_QUERY_THROW );
1061 uno::Reference< office::XAnnotationEnumeration > xAnnotationEnumeration( xAnnotationAccess->createAnnotationEnumeration() );
1062
1063 sal_Int32 nIndex = 1;
1064
1065 while( xAnnotationEnumeration->hasMoreElements() )
1066 {
1067 EscherExContainer aComment10( rBinaryTagData10Atom, EPP_Comment10 );
1068 {
1069 uno::Reference< office::XAnnotation > xAnnotation( xAnnotationEnumeration->nextElement() );
1070
1071 geometry::RealPoint2D aRealPoint2D( xAnnotation->getPosition() );
1072 MapMode aMapDest( MapUnit::MapInch, Point(), Fraction( 1, 576 ), Fraction( 1, 576 ) );
1073 Point aPoint( OutputDevice::LogicToLogic( Point( static_cast< sal_Int32 >( aRealPoint2D.X * 100.0 ),
1074 static_cast<sal_Int32>(aRealPoint2D.Y * 100.0)), MapMode(MapUnit::Map100thMM), aMapDest));
1075
1076 OUString sAuthor( xAnnotation->getAuthor() );
1077 uno::Reference< text::XText > xText( xAnnotation->getTextRange() );
1078 OUString sText( xText->getString() );
1079 OUString sInitials( getInitials( sAuthor ) );
1080 util::DateTime aDateTime( xAnnotation->getDateTime() );
1081 if ( !sAuthor.isEmpty() )
1082 PPTWriter::WriteCString( rBinaryTagData10Atom, sAuthor );
1083 if ( !sText.isEmpty() )
1084 PPTWriter::WriteCString( rBinaryTagData10Atom, sText, 1 );
1085 if ( !sInitials.isEmpty() )
1086 PPTWriter::WriteCString( rBinaryTagData10Atom, sInitials, 2 );
1087
1088 sal_Int16 nMilliSeconds = static_cast<sal_Int16>(::rtl::math::round(static_cast<double>(aDateTime.NanoSeconds) / 1000000000.0));
1089 EscherExAtom aCommentAtom10( rBinaryTagData10Atom, EPP_CommentAtom10 );
1090 rBinaryTagData10Atom.WriteInt32( nIndex++ )
1091 .WriteInt16( aDateTime.Year )
1092 .WriteUInt16( aDateTime.Month )
1093 .WriteUInt16( aDateTime.Day ) // todo: day of week
1094 .WriteUInt16( aDateTime.Day )
1095 .WriteUInt16( aDateTime.Hours )
1096 .WriteUInt16( aDateTime.Minutes )
1097 .WriteUInt16( aDateTime.Seconds )
1098 .WriteInt16( nMilliSeconds )
1099 .WriteInt32( aPoint.X() )
1100 .WriteInt32( aPoint.Y() );
1101 }
1102 }
1103 }
1104 catch ( uno::Exception& )
1105 {
1106 }
1107 }
1108
ImplWriteNotes(sal_uInt32 nPageNum)1109 void PPTWriter::ImplWriteNotes( sal_uInt32 nPageNum )
1110 {
1111 mpPptEscherEx->PtReplaceOrInsert( EPP_Persist_Notes | nPageNum, mpStrm->Tell() );
1112 mpPptEscherEx->OpenContainer( EPP_Notes );
1113 mpPptEscherEx->AddAtom( 8, EPP_NotesAtom, 1 );
1114 mpStrm->WriteUInt32( nPageNum + 0x100 )
1115 .WriteUInt16( 3 ) // follow master...
1116 .WriteUInt16( 0 );
1117
1118 ImplCreateHeaderFooters( mXPagePropSet );
1119
1120 EscherSolverContainer aSolverContainer;
1121
1122 mpPptEscherEx->OpenContainer( EPP_PPDrawing );
1123 mpPptEscherEx->OpenContainer( ESCHER_DgContainer );
1124 mpPptEscherEx->EnterGroup(nullptr,nullptr);
1125
1126 ImplWritePage( GetLayout( 20 ), aSolverContainer, NOTICE, false ); // the shapes of the pages are created in the PPT document
1127
1128 mpPptEscherEx->LeaveGroup();
1129 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
1130 mpPptEscherEx->AddShape( ESCHER_ShpInst_Rectangle, ShapeFlag::Background | ShapeFlag::HaveShapeProperty );
1131 EscherPropertyContainer aPropOpt;
1132 aPropOpt.AddOpt( ESCHER_Prop_fillColor, 0xffffff ); // stock valued fill color
1133 aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0 );
1134 aPropOpt.AddOpt( ESCHER_Prop_fillRectRight, 0x8b9f8e );
1135 aPropOpt.AddOpt( ESCHER_Prop_fillRectBottom, 0x68bdde );
1136 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x120012 );
1137 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
1138 aPropOpt.AddOpt( ESCHER_Prop_bWMode, ESCHER_wDontShow );
1139 aPropOpt.AddOpt( ESCHER_Prop_fBackground, 0x10001 );
1140 aPropOpt.Commit( *mpStrm );
1141 mpPptEscherEx->CloseContainer(); // ESCHER_SpContainer
1142
1143 aSolverContainer.WriteSolver( *mpStrm );
1144
1145 mpPptEscherEx->CloseContainer(); // ESCHER_DgContainer
1146 mpPptEscherEx->CloseContainer(); // EPP_Drawing
1147 mpPptEscherEx->AddAtom( 32, EPP_ColorSchemeAtom, 0, 1 );
1148 mpStrm->WriteUInt32( 0xffffff ).WriteUInt32( 0x000000 ).WriteUInt32( 0x808080 ).WriteUInt32( 0x000000 ).WriteUInt32( 0x99cc00 ).WriteUInt32( 0xcc3333 ).WriteUInt32( 0xffcccc ).WriteUInt32( 0xb2b2b2 );
1149 mpPptEscherEx->CloseContainer(); // EPP_Notes
1150 };
1151
ImplWriteBackground(css::uno::Reference<css::beans::XPropertySet> const & rXPropSet)1152 void PPTWriter::ImplWriteBackground( css::uno::Reference< css::beans::XPropertySet > const & rXPropSet )
1153 {
1154 //************************ ******
1155 //** DEFAULT BACKGROUND SHAPE **
1156
1157 sal_uInt32 nFillColor = 0xffffff;
1158 sal_uInt32 nFillBackColor = 0;
1159
1160 mpPptEscherEx->OpenContainer( ESCHER_SpContainer );
1161 mpPptEscherEx->AddShape( ESCHER_ShpInst_Rectangle, ShapeFlag::Background | ShapeFlag::HaveShapeProperty );
1162
1163 // #i121183# Use real PageSize in 100th mm
1164 ::tools::Rectangle aRect(Point(0, 0), Size(maPageSize.Width, maPageSize.Height));
1165
1166 EscherPropertyContainer aPropOpt( mpPptEscherEx->GetGraphicProvider(), mpPicStrm.get(), aRect );
1167 aPropOpt.AddOpt( ESCHER_Prop_fillType, ESCHER_FillSolid );
1168 css::drawing::FillStyle aFS( css::drawing::FillStyle_NONE );
1169 if ( ImplGetPropertyValue( rXPropSet, "FillStyle" ) )
1170 mAny >>= aFS;
1171
1172 switch( aFS )
1173 {
1174 case css::drawing::FillStyle_GRADIENT :
1175 {
1176 aPropOpt.CreateGradientProperties( rXPropSet );
1177 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x1f001e );
1178 aPropOpt.GetOpt( ESCHER_Prop_fillColor, nFillColor );
1179 aPropOpt.GetOpt( ESCHER_Prop_fillBackColor, nFillBackColor );
1180 }
1181 break;
1182
1183 case css::drawing::FillStyle_BITMAP :
1184 aPropOpt.CreateGraphicProperties( rXPropSet, "FillBitmap", true );
1185 break;
1186
1187 case css::drawing::FillStyle_HATCH :
1188 aPropOpt.CreateGraphicProperties( rXPropSet, "FillHatch", true );
1189 break;
1190
1191 case css::drawing::FillStyle_SOLID :
1192 {
1193 if ( ImplGetPropertyValue( rXPropSet, "FillColor" ) )
1194 {
1195 nFillColor = EscherEx::GetColor( *o3tl::doAccess<sal_uInt32>(mAny) );
1196 nFillBackColor = nFillColor ^ 0xffffff;
1197 }
1198 [[fallthrough]];
1199 }
1200 case css::drawing::FillStyle_NONE :
1201 default:
1202 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x120012 );
1203 break;
1204 }
1205 aPropOpt.AddOpt( ESCHER_Prop_fillColor, nFillColor );
1206 aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, nFillBackColor );
1207 aPropOpt.AddOpt( ESCHER_Prop_fillRectRight, PPTtoEMU( maDestPageSize.Width ) );
1208 aPropOpt.AddOpt( ESCHER_Prop_fillRectBottom, PPTtoEMU( maDestPageSize.Height ) );
1209 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
1210 aPropOpt.AddOpt( ESCHER_Prop_bWMode, ESCHER_bwWhite );
1211 aPropOpt.AddOpt( ESCHER_Prop_fBackground, 0x10001 );
1212 aPropOpt.Commit( *mpStrm );
1213 mpPptEscherEx->CloseContainer(); // ESCHER_SpContainer
1214 }
1215
ImplWriteVBA()1216 void PPTWriter::ImplWriteVBA()
1217 {
1218 if ( mpVBA )
1219 {
1220 sal_uInt32 nLen = mpVBA->TellEnd();
1221 if ( nLen > 8 )
1222 {
1223 nLen -= 8;
1224 mnVBAOleOfs = mpStrm->Tell();
1225 mpPptEscherEx->BeginAtom();
1226 mpStrm->WriteBytes(static_cast<sal_Int8 const *>(mpVBA->GetData()) + 8, nLen);
1227 mpPptEscherEx->EndAtom( EPP_ExOleObjStg, 0, 1 );
1228 }
1229 }
1230 }
1231
ImplWriteOLE()1232 void PPTWriter::ImplWriteOLE( )
1233 {
1234
1235 SvxMSExportOLEObjects aOleExport( mnCnvrtFlags );
1236
1237 for ( const auto& rxExOleObjEntry : maExOleObj )
1238 {
1239 PPTExOleObjEntry* pPtr = rxExOleObjEntry.get();
1240 std::unique_ptr<SvMemoryStream> pStrm;
1241 pPtr->nOfsB = mpStrm->Tell();
1242 switch ( pPtr->eType )
1243 {
1244 case NORMAL_OLE_OBJECT :
1245 {
1246 SdrObject* pSdrObj = GetSdrObjectFromXShape( pPtr->xShape );
1247 if ( auto pSdrOle2Obj = dynamic_cast< SdrOle2Obj* >(pSdrObj) )
1248 {
1249 const ::uno::Reference < embed::XEmbeddedObject >& xObj( pSdrOle2Obj->GetObjRef() );
1250 if( xObj.is() )
1251 {
1252 tools::SvRef<SotStorage> xTempStorage( new SotStorage( new SvMemoryStream(), true ) );
1253 aOleExport.ExportOLEObject( xObj, *xTempStorage );
1254
1255 //TODO/MBA: testing
1256 SvMemoryStream aStream;
1257 tools::SvRef<SotStorage> xCleanStorage( new SotStorage( false, aStream ) );
1258 xTempStorage->CopyTo( xCleanStorage.get() );
1259 // create a dummy content stream, the dummy content is necessary for ppt, but not for
1260 // doc files, so we can't share code.
1261 tools::SvRef<SotStorageStream> xStm = xCleanStorage->OpenSotStream( SVEXT_PERSIST_STREAM );
1262 xStm->WriteUInt32( 0 ) // no ClipboardId
1263 .WriteUInt32( 4 ) // no target device
1264 .WriteUInt32( 1 ) // aspect ratio
1265 .WriteInt32( -1 ) // L-Index
1266 .WriteUInt32( 0 ) // Advanced Flags
1267 .WriteUInt32( 0 ) // compression
1268 .WriteUInt32( 0 ) // Size
1269 .WriteUInt32( 0 ) // "
1270 .WriteUInt32( 0 );
1271 pStrm = xCleanStorage->CreateMemoryStream();
1272 }
1273 }
1274 }
1275 break;
1276
1277 case OCX_CONTROL :
1278 {
1279 if ( pPtr->xControlModel.is() )
1280 {
1281 OUString aName;
1282 //Initialize the graphic size which will be used on export
1283 css::awt::Size aSize( pPtr->xShape->getSize() );
1284 tools::SvRef<SotStorage> xDest( new SotStorage( new SvMemoryStream(), true ) );
1285 bool bOk = oox::ole::MSConvertOCXControls::WriteOCXStream( mXModel, xDest, pPtr->xControlModel, aSize, aName );
1286 if ( bOk )
1287 pStrm = xDest->CreateMemoryStream();
1288 }
1289 }
1290 }
1291 if ( pStrm )
1292 {
1293 mpPptEscherEx->BeginAtom();
1294 pStrm->Seek( STREAM_SEEK_TO_END );
1295 sal_uInt32 npStrmSize = pStrm->Tell();
1296 mpStrm->WriteUInt32( npStrmSize ); // uncompressed size
1297
1298 pStrm->Seek( 0 );
1299 ZCodec aZCodec( 0x8000, 0x8000 );
1300 aZCodec.BeginCompression();
1301 aZCodec.Compress( *pStrm, *mpStrm );
1302 aZCodec.EndCompression();
1303 pStrm.reset();
1304 mpPptEscherEx->EndAtom( EPP_ExOleObjStg, 0, 1 );
1305 }
1306 }
1307 }
1308
1309 // write PersistantTable and UserEditAtom
1310
ImplWriteAtomEnding()1311 void PPTWriter::ImplWriteAtomEnding()
1312 {
1313
1314 #define EPP_LastViewTypeSlideView 1
1315
1316 sal_uInt32 i, nPos, nOfs, nPersistOfs = mpStrm->Tell();
1317 sal_uInt32 nPersistEntrys = 0;
1318 mpStrm->WriteUInt32( 0 ).WriteUInt32( 0 ).WriteUInt32( 0 ); // skip record header and first entry
1319
1320 // write document persist
1321 nPersistEntrys++;
1322 mpStrm->WriteUInt32( 0 );
1323 // write MasterPages persists
1324 for ( i = 0; i < mnMasterPages; i++ )
1325 {
1326 nOfs = mpPptEscherEx->PtGetOffsetByID( EPP_Persist_MainMaster | i );
1327 if ( nOfs )
1328 {
1329 mpStrm->WriteUInt32( nOfs );
1330 mpPptEscherEx->InsertAtPersistOffset( EPP_MAINMASTER_PERSIST_KEY | i, ++nPersistEntrys );
1331 }
1332 }
1333 // write MainNotesMaster persist
1334 nOfs = mpPptEscherEx->PtGetOffsetByID( EPP_Persist_MainNotes );
1335 if ( nOfs )
1336 {
1337 mpStrm->WriteUInt32( nOfs );
1338 mpPptEscherEx->InsertAtPersistOffset( EPP_MAINNOTESMASTER_PERSIST_KEY, ++nPersistEntrys );
1339 }
1340 // write slide persists -> we have to write a valid value into EPP_SlidePersistAtome too
1341 for ( i = 0; i < mnPages; i++ )
1342 {
1343 nOfs = mpPptEscherEx->PtGetOffsetByID( EPP_Persist_Slide | i );
1344 if ( nOfs )
1345 {
1346 mpStrm->WriteUInt32( nOfs );
1347 mpPptEscherEx->InsertAtPersistOffset( EPP_MAINSLIDE_PERSIST_KEY | i, ++nPersistEntrys );
1348 }
1349 }
1350 // write Notes persists
1351 for ( i = 0; i < mnPages; i++ )
1352 {
1353 nOfs = mpPptEscherEx->PtGetOffsetByID( EPP_Persist_Notes | i );
1354 if ( nOfs )
1355 {
1356 mpStrm->WriteUInt32( nOfs );
1357 mpPptEscherEx->InsertAtPersistOffset( EPP_MAINNOTES_PERSIST_KEY | i, ++nPersistEntrys );
1358 }
1359 }
1360 // Ole persists
1361 for ( const auto& rxExOleObjEntry : maExOleObj )
1362 {
1363 PPTExOleObjEntry* pPtr = rxExOleObjEntry.get();
1364 nOfs = mpPptEscherEx->PtGetOffsetByID( EPP_Persist_ExObj );
1365 if ( nOfs )
1366 {
1367 nPersistEntrys++;
1368 mpStrm->WriteUInt32( pPtr->nOfsB );
1369 sal_uInt32 nOldPos, nPersOfs = nOfs + pPtr->nOfsA + 16 + 8; // 8 bytes atom header, +16 to the persist entry
1370 nOldPos = mpStrm->Tell();
1371 mpStrm->Seek( nPersOfs );
1372 mpStrm->WriteUInt32( nPersistEntrys );
1373 mpStrm->Seek( nOldPos );
1374 }
1375 }
1376 // VB persist
1377 if ( mnVBAOleOfs && mpVBA )
1378 {
1379 nOfs = mpPptEscherEx->PtGetOffsetByID( EPP_Persist_VBAInfoAtom );
1380 if ( nOfs )
1381 {
1382 nPersistEntrys++;
1383 sal_uInt32 n1, n2;
1384
1385 mpVBA->Seek( 0 );
1386 mpVBA->ReadUInt32( n1 )
1387 .ReadUInt32( n2 );
1388
1389 mpStrm->WriteUInt32( mnVBAOleOfs );
1390 sal_uInt32 nOldPos = mpStrm->Tell();
1391 mpStrm->Seek( nOfs ); // Fill the VBAInfoAtom with the correct index to the persisttable
1392 mpStrm->WriteUInt32( nPersistEntrys )
1393 .WriteUInt32( n1 )
1394 .WriteInt32( 2 );
1395 mpStrm->Seek( nOldPos );
1396
1397 }
1398 }
1399 nPos = mpStrm->Tell();
1400 mpStrm->Seek( nPersistOfs );
1401 mpPptEscherEx->AddAtom( ( nPersistEntrys + 1 ) << 2, EPP_PersistPtrIncrementalBlock ); // insert Record Header
1402 mpStrm->WriteUInt32( ( nPersistEntrys << 20 ) | 1 );
1403 mpStrm->Seek( nPos );
1404
1405 mpCurUserStrm->WriteUInt32( nPos ); // set offset to current edit
1406 mpPptEscherEx->AddAtom( 28, EPP_UserEditAtom );
1407 mpStrm->WriteInt32( 0x100 ) // last slide ID
1408 .WriteUInt32( 0x03000dbc ) // minor and major app version that did the save
1409 .WriteUInt32( 0 ) // offset last save, 0 after a full save
1410 .WriteUInt32( nPersistOfs ) // File offset to persist pointers for this save operation
1411 .WriteUInt32( 1 ) // Persist reference to the document persist object
1412 .WriteUInt32( nPersistEntrys ) // max persists written, Seed value for persist object id management
1413 .WriteInt16( EPP_LastViewTypeSlideView ) // last view type
1414 .WriteInt16( 0x12 ); // padword
1415 }
1416
1417 // - exported function -
1418
ExportPPT(const std::vector<css::beans::PropertyValue> & rMediaData,tools::SvRef<SotStorage> const & rSvStorage,css::uno::Reference<css::frame::XModel> const & rXModel,css::uno::Reference<css::task::XStatusIndicator> const & rXStatInd,SvMemoryStream * pVBA,sal_uInt32 nCnvrtFlags)1419 extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool ExportPPT( const std::vector< css::beans::PropertyValue >& rMediaData,
1420 tools::SvRef<SotStorage> const & rSvStorage,
1421 css::uno::Reference< css::frame::XModel > const & rXModel,
1422 css::uno::Reference< css::task::XStatusIndicator > const & rXStatInd,
1423 SvMemoryStream* pVBA,
1424 sal_uInt32 nCnvrtFlags )
1425 {
1426 PPTWriter aPPTWriter( rSvStorage, rXModel, rXStatInd, pVBA, nCnvrtFlags );
1427 aPPTWriter.exportPPT(rMediaData);
1428 bool bStatus = aPPTWriter.IsValid();
1429 return bStatus;
1430 }
1431
SaveVBA(SfxObjectShell & rDocShell,SvMemoryStream * & pBas)1432 extern "C" SAL_DLLPUBLIC_EXPORT sal_Bool SaveVBA( SfxObjectShell& rDocShell, SvMemoryStream*& pBas )
1433 {
1434 tools::SvRef<SotStorage> xDest( new SotStorage( new SvMemoryStream(), true ) );
1435 SvxImportMSVBasic aMSVBas( rDocShell, *xDest );
1436 aMSVBas.SaveOrDelMSVBAStorage( true, "_MS_VBA_Overhead" );
1437
1438 tools::SvRef<SotStorage> xOverhead = xDest->OpenSotStorage( "_MS_VBA_Overhead" );
1439 if ( xOverhead.is() && ( xOverhead->GetError() == ERRCODE_NONE ) )
1440 {
1441 tools::SvRef<SotStorage> xOverhead2 = xOverhead->OpenSotStorage( "_MS_VBA_Overhead" );
1442 if ( xOverhead2.is() && ( xOverhead2->GetError() == ERRCODE_NONE ) )
1443 {
1444 tools::SvRef<SotStorageStream> xTemp = xOverhead2->OpenSotStream( "_MS_VBA_Overhead2" );
1445 if ( xTemp.is() && ( xTemp->GetError() == ERRCODE_NONE ) )
1446 {
1447 sal_uInt32 nLen = xTemp->GetSize();
1448 if ( nLen )
1449 {
1450 char* pTemp = new char[ nLen ];
1451 xTemp->Seek( STREAM_SEEK_TO_BEGIN );
1452 xTemp->ReadBytes(pTemp, nLen);
1453 pBas = new SvMemoryStream( pTemp, nLen, StreamMode::READ );
1454 pBas->ObjectOwnsMemory( true );
1455 return true;
1456 }
1457 }
1458 }
1459 }
1460
1461 return false;
1462 }
1463
1464 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1465