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 <sal/config.h>
21
22 #include <osl/endian.h>
23 #include <vcl/svapp.hxx>
24 #include <unotools/tempfile.hxx>
25 #include <tools/diagnose_ex.h>
26 #include <tools/UnitConversion.hxx>
27 #include <math.h>
28 #include <editeng/eeitem.hxx>
29 #include <editeng/editdata.hxx>
30 #include <sot/storage.hxx>
31 #include <sot/storinfo.hxx>
32 #include <sot/stg.hxx>
33 #include <com/sun/star/embed/Aspects.hpp>
34 #include <com/sun/star/embed/XEmbeddedObject.hpp>
35 #include <com/sun/star/frame/XModel.hpp>
36 #include <com/sun/star/office/XAnnotation.hpp>
37 #include <com/sun/star/office/XAnnotationAccess.hpp>
38 #include <com/sun/star/text/XText.hpp>
39 #include <com/sun/star/geometry/RealPoint2D.hpp>
40 #include <com/sun/star/util/DateTime.hpp>
41 #include <com/sun/star/drawing/BitmapMode.hpp>
42 #include <filter/msfilter/svdfppt.hxx>
43 #include <svx/xflgrit.hxx>
44 #include <svx/xbtmpit.hxx>
45 #include <svx/svdtrans.hxx>
46 #include <svx/svdmodel.hxx>
47 #include <svx/svdpage.hxx>
48 #include <svx/svdobj.hxx>
49 #include <svx/svdogrp.hxx>
50 #include <svx/svdorect.hxx>
51 #include <svx/svdopage.hxx>
52 #include <svx/svdograf.hxx>
53 #include <svx/svdopath.hxx>
54 #include <svx/svdotable.hxx>
55 #include <svx/xfillit0.hxx>
56 #include <svx/xflbstit.hxx>
57 #include <svx/xflbmtit.hxx>
58 #include <svx/xflclit.hxx>
59 #include <svx/xfltrit.hxx>
60 #include <editeng/outlobj.hxx>
61 #include <editeng/numdef.hxx>
62 #include <svx/sdasitm.hxx>
63 #include <svx/sdmetitm.hxx>
64 #include <svx/sdtagitm.hxx>
65 #include <svx/sdtditm.hxx>
66 #include <svx/sdtfsitm.hxx>
67 #include <svx/sdtmfitm.hxx>
68 #include <svx/xlineit0.hxx>
69 #include <svx/xlnclit.hxx>
70 #include <svx/xlnwtit.hxx>
71 #include <editeng/hngpnctitem.hxx>
72 #include <editeng/forbiddenruleitem.hxx>
73 #include <svx/svdoashp.hxx>
74 #include <editeng/tstpitem.hxx>
75 #include <editeng/editids.hrc>
76
77 #include <editeng/adjustitem.hxx>
78 #include <editeng/escapementitem.hxx>
79 #include <editeng/colritem.hxx>
80 #include <editeng/fhgtitem.hxx>
81 #include <editeng/wghtitem.hxx>
82 #include <editeng/postitem.hxx>
83 #include <editeng/udlnitem.hxx>
84 #include <editeng/crossedoutitem.hxx>
85 #include <editeng/shdditem.hxx>
86 #include <editeng/charreliefitem.hxx>
87 #include <editeng/fontitem.hxx>
88 #include <svx/svdoutl.hxx>
89 #include <editeng/lspcitem.hxx>
90 #include <editeng/ulspitem.hxx>
91 #include <editeng/lrspitem.hxx>
92 #include <editeng/numitem.hxx>
93 #include <vcl/gdimtf.hxx>
94 #include <vcl/BitmapReadAccess.hxx>
95 #include <svx/svditer.hxx>
96 #include <editeng/flditem.hxx>
97 #include <tools/zcodec.hxx>
98 #include <filter/msfilter/svxmsbas.hxx>
99 #include <sfx2/objsh.hxx>
100 #include <editeng/brushitem.hxx>
101 #include <editeng/langitem.hxx>
102 #include <svx/svdoole2.hxx>
103 #include <svx/unoapi.hxx>
104 #include <toolkit/helper/vclunohelper.hxx>
105 #include <com/sun/star/container/XIndexContainer.hpp>
106 #include <com/sun/star/drawing/XControlShape.hpp>
107 #include <com/sun/star/form/XFormComponent.hpp>
108 #include <com/sun/star/beans/XPropertySet.hpp>
109 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
110 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
111 #include <com/sun/star/awt/Size.hpp>
112 #include <com/sun/star/drawing/FillStyle.hpp>
113 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
114 #include <editeng/frmdiritem.hxx>
115 #include <svx/sdtfchim.hxx>
116 #include <com/sun/star/awt/Gradient.hpp>
117 #include <com/sun/star/table/XMergeableCellRange.hpp>
118 #include <com/sun/star/table/BorderLine2.hpp>
119 #include <com/sun/star/table/BorderLineStyle.hpp>
120 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
121 #include <svtools/embedhlp.hxx>
122 #include <o3tl/enumrange.hxx>
123 #include <o3tl/safeint.hxx>
124 #include <o3tl/sorted_vector.hxx>
125 #include <sal/log.hxx>
126
127 #include <algorithm>
128 #include <cassert>
129 #include <utility>
130 #include <rtl/strbuf.hxx>
131 #include <tools/time.hxx>
132 #include <memory>
133
134 // PPT ColorScheme Slots
135 #define PPT_COLSCHEME (0x08000000)
136 #define PPT_COLSCHEME_HINTERGRUND (0x08000000)
137 #define PPT_COLSCHEME_TEXT_UND_ZEILEN (0x08000001)
138 #define PPT_COLSCHEME_TITELTEXT (0x08000003)
139 #define PPT_COLSCHEME_A_UND_HYPERLINK (0x08000006)
140
141 #define ANSI_CHARSET 0
142 #define SYMBOL_CHARSET 2
143
144 /* Font Families */
145 #define FF_ROMAN 0x10
146 #define FF_SWISS 0x20
147 #define FF_MODERN 0x30
148 #define FF_SCRIPT 0x40
149 #define FF_DECORATIVE 0x50
150
151 #define DEFAULT_PITCH 0x00
152 #define FIXED_PITCH 0x01
153 #define VARIABLE_PITCH 0x02
154
155 using namespace ::com::sun::star ;
156 using namespace uno ;
157 using namespace beans ;
158 using namespace drawing ;
159 using namespace container ;
160 using namespace table ;
161
PowerPointImportParam(SvStream & rDocStrm)162 PowerPointImportParam::PowerPointImportParam( SvStream& rDocStrm ) :
163 rDocStream ( rDocStrm ),
164 nImportFlags ( 0 )
165 {
166 }
167
ReadPptCurrentUserAtom(SvStream & rIn,PptCurrentUserAtom & rAtom)168 SvStream& ReadPptCurrentUserAtom( SvStream& rIn, PptCurrentUserAtom& rAtom )
169 {
170 DffRecordHeader aHd;
171 ReadDffRecordHeader( rIn, aHd );
172 if ( aHd.nRecType == PPT_PST_CurrentUserAtom )
173 {
174 sal_uInt32 nLen;
175 sal_uInt16 nUserNameLen, nPad;
176 rIn.ReadUInt32( nLen )
177 .ReadUInt32( rAtom.nMagic )
178 .ReadUInt32( rAtom.nCurrentUserEdit )
179 .ReadUInt16( nUserNameLen )
180 .ReadUInt16( rAtom.nDocFileVersion )
181 .ReadUChar( rAtom.nMajorVersion )
182 .ReadUChar( rAtom.nMinorVersion )
183 .ReadUInt16( nPad );
184 rAtom.aCurrentUser = SvxMSDffManager::MSDFFReadZString( rIn, nUserNameLen, true );
185 }
186 aHd.SeekToEndOfRecord( rIn );
187 return rIn;
188 }
189
Clear()190 void PptSlidePersistAtom::Clear()
191 {
192 nReserved = nPsrReference = nFlags = nNumberTexts = nSlideId = 0;
193 }
194
ReadPptSlidePersistAtom(SvStream & rIn,PptSlidePersistAtom & rAtom)195 SvStream& ReadPptSlidePersistAtom( SvStream& rIn, PptSlidePersistAtom& rAtom )
196 {
197 DffRecordHeader aHd;
198 ReadDffRecordHeader( rIn, aHd );
199 rIn
200 .ReadUInt32( rAtom.nPsrReference )
201 .ReadUInt32( rAtom.nFlags )
202 .ReadUInt32( rAtom.nNumberTexts )
203 .ReadUInt32( rAtom.nSlideId );
204 aHd.SeekToEndOfRecord( rIn );
205 return rIn;
206 }
207
PptSlidePersistList()208 PptSlidePersistList::PptSlidePersistList() {}
209
~PptSlidePersistList()210 PptSlidePersistList::~PptSlidePersistList() {}
211
FindPage(sal_uInt32 nId) const212 sal_uInt16 PptSlidePersistList::FindPage(sal_uInt32 nId) const
213 {
214 for ( size_t i=0; i < mvEntries.size(); i++ )
215 {
216 if (mvEntries[ i ]->GetSlideId() == nId) return i;
217 }
218 return PPTSLIDEPERSIST_ENTRY_NOTFOUND;
219 }
220
ReadPptInteractiveInfoAtom(SvStream & rIn,PptInteractiveInfoAtom & rAtom)221 SvStream& ReadPptInteractiveInfoAtom( SvStream& rIn, PptInteractiveInfoAtom& rAtom )
222 {
223 rIn.ReadUInt32( rAtom.nSoundRef )
224 .ReadUInt32( rAtom.nExHyperlinkId )
225 .ReadUChar( rAtom.nAction )
226 .ReadUChar( rAtom.nOleVerb )
227 .ReadUChar( rAtom.nJump )
228 .ReadUChar( rAtom.nFlags )
229 .ReadUChar( rAtom.nHyperlinkType )
230 .ReadUChar( rAtom.nUnknown1 )
231 .ReadUChar( rAtom.nUnknown2 )
232 .ReadUChar( rAtom.nUnknown3 );
233 return rIn;
234 }
235
ReadPptExOleObjAtom(SvStream & rIn,PptExOleObjAtom & rAtom)236 SvStream& ReadPptExOleObjAtom( SvStream& rIn, PptExOleObjAtom& rAtom )
237 {
238 sal_uInt32 nDummy1;
239 sal_uInt32 nDummy2;
240 sal_uInt32 nDummy4;
241
242 rIn.ReadUInt32( rAtom.nAspect )
243 .ReadUInt32( nDummy1 )
244 .ReadUInt32( rAtom.nId )
245 .ReadUInt32( nDummy2 )
246 .ReadUInt32( rAtom.nPersistPtr )
247 .ReadUInt32( nDummy4 );
248 return rIn;
249 }
250
ReadPptDocumentAtom(SvStream & rIn,PptDocumentAtom & rAtom)251 SvStream& ReadPptDocumentAtom(SvStream& rIn, PptDocumentAtom& rAtom)
252 {
253 // Actual format:
254 // 00 aSlidePageSizeXY 8
255 // 08 aNotesPageSizeXY 8
256 // 16 aZoomRatio (OLE) 8
257 // 24 nNotesMasterPersist 4
258 // 28 nHandoutMasterPersist 4
259 // 32 n1stPageNumber 2
260 // 34 ePageFormat 2
261 // 36 bEmbeddedTrueType 1
262 // 37 bOmitTitlePlace 1
263 // 38 bRightToLeft 1
264 // 39 bShowComments 1
265
266 DffRecordHeader aHd;
267 sal_Int32 nSlideX,nSlideY, nNoticeX, nNoticeY, nDummy;
268 sal_uInt16 nSlidePageFormat;
269 sal_Int8 nEmbeddedTrueType, nTitlePlaceHoldersOmitted, nRightToLeft, nShowComments;
270
271 ReadDffRecordHeader( rIn, aHd );
272 rIn
273 .ReadInt32( nSlideX ).ReadInt32( nSlideY )
274 .ReadInt32( nNoticeX ).ReadInt32( nNoticeY )
275 .ReadInt32( nDummy ).ReadInt32( nDummy ) // skip ZoomRatio
276 .ReadUInt32( rAtom.nNotesMasterPersist )
277 .ReadUInt32( rAtom.nHandoutMasterPersist )
278 .ReadUInt16( rAtom.n1stPageNumber )
279 .ReadUInt16( nSlidePageFormat )
280 .ReadSChar( nEmbeddedTrueType )
281 .ReadSChar( nTitlePlaceHoldersOmitted )
282 .ReadSChar( nRightToLeft )
283 .ReadSChar( nShowComments );
284 // clamp dodgy data to avoid overflow in later calculations
285 const sal_Int32 nPageClamp = SAL_MAX_INT32/5;
286 rAtom.aSlidesPageSize.setWidth( std::clamp<sal_Int32>(nSlideX, -nPageClamp, nPageClamp) );
287 rAtom.aSlidesPageSize.setHeight( std::clamp<sal_Int32>(nSlideY, -nPageClamp, nPageClamp) );
288 const sal_Int32 nNoteClamp = 65536;
289 rAtom.aNotesPageSize.setWidth( std::clamp<sal_Int32>(nNoticeX, -nNoteClamp, nNoteClamp) );
290 rAtom.aNotesPageSize.setHeight( std::clamp<sal_Int32>(nNoticeY, -nNoteClamp, nNoteClamp) );
291 rAtom.eSlidesPageFormat = static_cast<PptPageFormat>(nSlidePageFormat);
292 rAtom.bEmbeddedTrueType = nEmbeddedTrueType;
293 rAtom.bTitlePlaceholdersOmitted = nTitlePlaceHoldersOmitted;
294 rAtom.bRightToLeft = nRightToLeft;
295 rAtom.bShowComments = nShowComments;
296 aHd.SeekToEndOfRecord( rIn );
297 return rIn;
298 }
299
Clear()300 void PptSlideLayoutAtom::Clear()
301 {
302 eLayout = PptSlideLayout::TITLESLIDE;
303 for (PptPlaceholder & i : aPlaceholderId)
304 i = PptPlaceholder::NONE;
305 }
306
ReadPptSlideLayoutAtom(SvStream & rIn,PptSlideLayoutAtom & rAtom)307 SvStream& ReadPptSlideLayoutAtom( SvStream& rIn, PptSlideLayoutAtom& rAtom )
308 {
309 sal_Int32 nTmp;
310 rIn.ReadInt32(nTmp);
311 rAtom.eLayout = static_cast<PptSlideLayout>(nTmp);
312 static_assert(sizeof(rAtom.aPlaceholderId) == 8, "wrong size of serialized array");
313 rIn.ReadBytes(rAtom.aPlaceholderId, 8);
314 return rIn;
315 }
316
ReadPptSlideAtom(SvStream & rIn,PptSlideAtom & rAtom)317 SvStream& ReadPptSlideAtom( SvStream& rIn, PptSlideAtom& rAtom )
318 {
319 DffRecordHeader aHd;
320 ReadDffRecordHeader( rIn, aHd );
321 ReadPptSlideLayoutAtom( rIn, rAtom.aLayout );
322 rIn.ReadUInt32( rAtom.nMasterId )
323 .ReadUInt32( rAtom.nNotesId )
324 .ReadUInt16( rAtom.nFlags );
325 aHd.SeekToEndOfRecord( rIn );
326 return rIn;
327 }
328
Clear()329 void PptSlideAtom::Clear()
330 {
331 nMasterId = nNotesId = 0;
332 nFlags = 0;
333 }
334
ReadPptNotesAtom(SvStream & rIn,PptNotesAtom & rAtom)335 SvStream& ReadPptNotesAtom( SvStream& rIn, PptNotesAtom& rAtom )
336 {
337 DffRecordHeader aHd;
338 ReadDffRecordHeader( rIn, aHd );
339 rIn
340 .ReadUInt32( rAtom.nSlideId )
341 .ReadUInt16( rAtom.nFlags );
342 aHd.SeekToEndOfRecord( rIn );
343 return rIn;
344 }
345
Clear()346 void PptNotesAtom::Clear()
347 {
348 nSlideId = 0;
349 nFlags = 0;
350 }
351
PptColorSchemeAtom()352 PptColorSchemeAtom::PptColorSchemeAtom()
353 {
354 }
355
GetColor(sal_uInt16 nNum) const356 Color PptColorSchemeAtom::GetColor( sal_uInt16 nNum ) const
357 {
358 Color aRetval;
359 if ( nNum < 8 )
360 {
361 nNum <<= 2;
362 aRetval.SetRed( aData[ nNum++ ] );
363 aRetval.SetGreen( aData[ nNum++ ] );
364 aRetval.SetBlue( aData[ nNum++ ] );
365 }
366 return aRetval;
367 }
368
ReadPptColorSchemeAtom(SvStream & rIn,PptColorSchemeAtom & rAtom)369 SvStream& ReadPptColorSchemeAtom( SvStream& rIn, PptColorSchemeAtom& rAtom )
370 {
371 DffRecordHeader aHd;
372 ReadDffRecordHeader( rIn, aHd );
373 rIn.ReadBytes(rAtom.aData, 32);
374 aHd.SeekToEndOfRecord( rIn );
375 return rIn;
376 }
377
ReadPptFontEntityAtom(SvStream & rIn,PptFontEntityAtom & rAtom)378 SvStream& ReadPptFontEntityAtom( SvStream& rIn, PptFontEntityAtom& rAtom )
379 {
380 DffRecordHeader aHd;
381 ReadDffRecordHeader( rIn, aHd );
382 sal_Unicode nTemp, cData[ 32 ];
383 rIn.ReadBytes(cData, 64);
384
385 sal_uInt8 lfCharset, lfPitchAndFamily;
386
387 rIn.ReadUChar( lfCharset )
388 .ReadUChar( rAtom.lfClipPrecision )
389 .ReadUChar( rAtom.lfQuality )
390 .ReadUChar( lfPitchAndFamily );
391
392 switch( lfCharset )
393 {
394 case SYMBOL_CHARSET :
395 rAtom.eCharSet = RTL_TEXTENCODING_SYMBOL;
396 break;
397 case ANSI_CHARSET :
398 rAtom.eCharSet = RTL_TEXTENCODING_MS_1252;
399 break;
400
401 default :
402 rAtom.eCharSet = osl_getThreadTextEncoding();
403 }
404 switch ( lfPitchAndFamily & 0xf0 )
405 {
406 case FF_ROMAN:
407 rAtom.eFamily = FAMILY_ROMAN;
408 break;
409
410 case FF_SWISS:
411 rAtom.eFamily = FAMILY_SWISS;
412 break;
413
414 case FF_MODERN:
415 rAtom.eFamily = FAMILY_MODERN;
416 break;
417
418 case FF_SCRIPT:
419 rAtom.eFamily = FAMILY_SCRIPT;
420 break;
421
422 case FF_DECORATIVE:
423 rAtom.eFamily = FAMILY_DECORATIVE;
424 break;
425
426 default:
427 rAtom.eFamily = FAMILY_DONTKNOW;
428 break;
429 }
430
431 switch ( lfPitchAndFamily & 0x0f )
432 {
433 case FIXED_PITCH:
434 rAtom.ePitch = PITCH_FIXED;
435 break;
436
437 case DEFAULT_PITCH:
438 case VARIABLE_PITCH:
439 default:
440 rAtom.ePitch = PITCH_VARIABLE;
441 break;
442 }
443 sal_uInt16 i;
444 for ( i = 0; i < 32; i++ )
445 {
446 nTemp = cData[ i ];
447 if ( !nTemp )
448 break;
449 #ifdef OSL_BIGENDIAN
450 cData[ i ] = ( nTemp >> 8 ) | ( nTemp << 8 );
451 #endif
452 }
453 rAtom.aName = OUString(cData, i);
454 OutputDevice* pDev = Application::GetDefaultDevice();
455 rAtom.bAvailable = pDev->IsFontAvailable( rAtom.aName );
456 aHd.SeekToEndOfRecord( rIn );
457 return rIn;
458 }
459
ReadPptUserEditAtom(SvStream & rIn,PptUserEditAtom & rAtom)460 SvStream& ReadPptUserEditAtom( SvStream& rIn, PptUserEditAtom& rAtom )
461 {
462 sal_Int16 lastViewType = 0;
463 ReadDffRecordHeader( rIn, rAtom.aHd );
464 rIn
465 .ReadInt32( rAtom.nLastSlideID )
466 .ReadUInt32( rAtom.nVersion )
467 .ReadUInt32( rAtom.nOffsetLastEdit )
468 .ReadUInt32( rAtom.nOffsetPersistDirectory )
469 .ReadUInt32( rAtom.nDocumentRef )
470 .ReadUInt32( rAtom.nMaxPersistWritten )
471 .ReadInt16( lastViewType );
472 rAtom.eLastViewType = static_cast<PptViewTypeEnum>(lastViewType);
473 rAtom.aHd.SeekToEndOfRecord(rIn);
474 return rIn;
475 }
476
Clear()477 void PptOEPlaceholderAtom::Clear()
478 {
479 nPlacementId = 0;
480 nPlaceholderSize = 0;
481 nPlaceholderId = PptPlaceholder::NONE;
482 }
483
ReadPptOEPlaceholderAtom(SvStream & rIn,PptOEPlaceholderAtom & rAtom)484 SvStream& ReadPptOEPlaceholderAtom( SvStream& rIn, PptOEPlaceholderAtom& rAtom )
485 {
486 rIn.ReadUInt32( rAtom.nPlacementId );
487 sal_uInt8 nTmp;
488 rIn.ReadUChar(nTmp);
489 rAtom.nPlaceholderId = static_cast<PptPlaceholder>(nTmp);
490 rIn.ReadUChar( rAtom.nPlaceholderSize );
491 return rIn;
492 }
493
PptSlidePersistEntry()494 PptSlidePersistEntry::PptSlidePersistEntry() :
495 nSlidePersistStartOffset( 0 ),
496 nSlidePersistEndOffset ( 0 ),
497 nBackgroundOffset ( 0 ),
498 nDrawingDgId ( 0xffffffff ),
499 pBObj ( nullptr ),
500 ePageKind ( PPT_MASTERPAGE ),
501 bNotesMaster ( false ),
502 bHandoutMaster ( false ),
503 bStarDrawFiller ( false )
504 {
505 HeaderFooterOfs[ 0 ] = HeaderFooterOfs[ 1 ] = HeaderFooterOfs[ 2 ] = HeaderFooterOfs[ 3 ] = 0;
506 }
507
~PptSlidePersistEntry()508 PptSlidePersistEntry::~PptSlidePersistEntry()
509 {
510 }
511
SdrEscherImport(PowerPointImportParam & rParam,const OUString & rBaseURL)512 SdrEscherImport::SdrEscherImport( PowerPointImportParam& rParam, const OUString& rBaseURL ) :
513 SvxMSDffManager ( rParam.rDocStream, rBaseURL ),
514 nStreamLen ( 0 ),
515 rImportParam ( rParam )
516 {
517 }
518
~SdrEscherImport()519 SdrEscherImport::~SdrEscherImport()
520 {
521 }
522
GetSlideLayoutAtom() const523 const PptSlideLayoutAtom* SdrEscherImport::GetSlideLayoutAtom() const
524 {
525 return nullptr;
526 }
527
ReadString(OUString & rStr) const528 bool SdrEscherImport::ReadString( OUString& rStr ) const
529 {
530 bool bRet = false;
531 DffRecordHeader aStrHd;
532 ReadDffRecordHeader( rStCtrl, aStrHd );
533 if (aStrHd.nRecType == PPT_PST_TextBytesAtom
534 || aStrHd.nRecType == PPT_PST_TextCharsAtom
535 || aStrHd.nRecType == PPT_PST_CString)
536 {
537 bool bUniCode =
538 (aStrHd.nRecType == PPT_PST_TextCharsAtom
539 || aStrHd.nRecType == PPT_PST_CString);
540 sal_uLong nBytes = aStrHd.nRecLen;
541 rStr = MSDFFReadZString( rStCtrl, nBytes, bUniCode );
542 bRet = aStrHd.SeekToEndOfRecord( rStCtrl );
543 }
544 else
545 aStrHd.SeekToBegOfRecord( rStCtrl );
546 return bRet;
547 }
548
GetColorFromPalette(sal_uInt16,Color &) const549 bool SdrEscherImport::GetColorFromPalette(sal_uInt16 /*nNum*/, Color& /*rColor*/) const
550 {
551 return false;
552 }
553
SeekToShape(SvStream &,SvxMSDffClientData *,sal_uInt32) const554 bool SdrEscherImport::SeekToShape( SvStream& /*rSt*/, SvxMSDffClientData* /*pClientData*/, sal_uInt32 /*nId*/) const
555 {
556 return false;
557 }
558
GetFontEnityAtom(sal_uInt32 nNum) const559 PptFontEntityAtom* SdrEscherImport::GetFontEnityAtom( sal_uInt32 nNum ) const
560 {
561 PptFontEntityAtom* pRetValue = nullptr;
562 if (m_pFonts && (nNum < m_pFonts->size()))
563 pRetValue = (*m_pFonts)[ nNum ].get();
564 return pRetValue;
565 }
566
ReadObjText(PPTTextObj *,SdrObject * pObj,SdPageCapsule) const567 SdrObject* SdrEscherImport::ReadObjText( PPTTextObj* /*pTextObj*/, SdrObject* pObj, SdPageCapsule /*pPage*/) const
568 {
569 return pObj;
570 }
571
ProcessClientAnchor2(SvStream & rSt,DffRecordHeader & rHd,DffObjData & rObj)572 void SdrEscherImport::ProcessClientAnchor2( SvStream& rSt, DffRecordHeader& rHd, DffObjData& rObj )
573 {
574 sal_Int32 l, t, r, b;
575 if ( rHd.nRecLen == 16 )
576 {
577 rSt.ReadInt32( l ).ReadInt32( t ).ReadInt32( r ).ReadInt32( b );
578 }
579 else
580 {
581 sal_Int16 ls, ts, rs, bs;
582 rSt.ReadInt16( ts ).ReadInt16( ls ).ReadInt16( rs ).ReadInt16( bs ); // the order of coordinates is a bit strange...
583 l = ls;
584 t = ts;
585 r = rs;
586 b = bs;
587 }
588 Scale( l );
589 Scale( t );
590 Scale( r );
591 Scale( b );
592 rObj.aChildAnchor = tools::Rectangle( l, t, r, b );
593 rObj.bChildAnchor = true;
594 };
595
RecolorGraphic(SvStream & rSt,sal_uInt32 nRecLen,Graphic & rGraphic)596 void SdrEscherImport::RecolorGraphic( SvStream& rSt, sal_uInt32 nRecLen, Graphic& rGraphic )
597 {
598 if ( rGraphic.GetType() != GraphicType::GdiMetafile )
599 return;
600
601 sal_uInt16 nX, nGlobalColorsCount, nFillColorsCount;
602
603 rSt.ReadUInt16( nX )
604 .ReadUInt16( nGlobalColorsCount )
605 .ReadUInt16( nFillColorsCount )
606 .ReadUInt16( nX )
607 .ReadUInt16( nX )
608 .ReadUInt16( nX );
609
610 if ( ( nGlobalColorsCount > 64 ) || ( nFillColorsCount > 64 ) )
611 return;
612
613 if ( static_cast<sal_uInt32>( ( nGlobalColorsCount + nFillColorsCount ) * 44 + 12 ) != nRecLen )
614 return;
615
616 sal_uInt32 OriginalGlobalColors[ 64 ];
617 sal_uInt32 NewGlobalColors[ 64 ];
618
619 sal_uInt32 i, j, nGlobalColorsChanged, nFillColorsChanged;
620 nGlobalColorsChanged = nFillColorsChanged = 0;
621
622 sal_uInt32* pCurrentOriginal = OriginalGlobalColors;
623 sal_uInt32* pCurrentNew = NewGlobalColors;
624 sal_uInt32* pCount = &nGlobalColorsChanged;
625 i = nGlobalColorsCount;
626
627 for ( j = 0; j < 2; j++ )
628 {
629 for ( ; i > 0; i-- )
630 {
631 sal_uInt32 nPos = rSt.Tell();
632 sal_uInt16 nChanged;
633 rSt.ReadUInt16( nChanged );
634 if ( nChanged & 1 )
635 {
636 sal_uInt8 nDummy, nRed, nGreen, nBlue;
637 sal_uInt32 nColor = 0;
638 sal_uInt32 nIndex;
639 rSt.ReadUChar( nDummy )
640 .ReadUChar( nRed )
641 .ReadUChar( nDummy )
642 .ReadUChar( nGreen )
643 .ReadUChar( nDummy )
644 .ReadUChar( nBlue )
645 .ReadUInt32( nIndex );
646
647 if ( nIndex < 8 )
648 {
649 Color aColor = MSO_CLR_ToColor( nIndex << 24 );
650 nRed = aColor.GetRed();
651 nGreen = aColor.GetGreen();
652 nBlue = aColor.GetBlue();
653 }
654 nColor = nRed | ( nGreen << 8 ) | ( nBlue << 16 );
655 *pCurrentNew++ = nColor;
656 rSt.ReadUChar( nDummy )
657 .ReadUChar( nRed )
658 .ReadUChar( nDummy )
659 .ReadUChar( nGreen )
660 .ReadUChar( nDummy )
661 .ReadUChar( nBlue );
662 nColor = nRed | ( nGreen << 8 ) | ( nBlue << 16 );
663 *pCurrentOriginal++ = nColor;
664 (*pCount)++;
665 }
666 rSt.Seek( nPos + 44 );
667 }
668 pCount = &nFillColorsChanged;
669 i = nFillColorsCount;
670 }
671 if ( !(nGlobalColorsChanged || nFillColorsChanged) )
672 return;
673
674 std::unique_ptr<Color[]> pSearchColors(new Color[ nGlobalColorsChanged ]);
675 std::unique_ptr<Color[]> pReplaceColors(new Color[ nGlobalColorsChanged ]);
676
677 for ( j = 0; j < nGlobalColorsChanged; j++ )
678 {
679 sal_uInt32 nSearch = OriginalGlobalColors[ j ];
680 sal_uInt32 nReplace = NewGlobalColors[ j ];
681
682 pSearchColors[ j ].SetRed( static_cast<sal_uInt8>(nSearch) );
683 pSearchColors[ j ].SetGreen( static_cast<sal_uInt8>( nSearch >> 8 ) );
684 pSearchColors[ j ].SetBlue( static_cast<sal_uInt8>( nSearch >> 16 ) );
685
686 pReplaceColors[ j ].SetRed( static_cast<sal_uInt8>(nReplace) );
687 pReplaceColors[ j ].SetGreen( static_cast<sal_uInt8>( nReplace >> 8 ) );
688 pReplaceColors[ j ].SetBlue( static_cast<sal_uInt8>( nReplace >> 16 ) );
689 }
690 GDIMetaFile aGdiMetaFile( rGraphic.GetGDIMetaFile() );
691 aGdiMetaFile.ReplaceColors( pSearchColors.get(), pReplaceColors.get(),
692 nGlobalColorsChanged );
693 rGraphic = aGdiMetaFile;
694 }
695
SanitizeEndPos(SvStream & rIn,sal_uLong nEndRecPos)696 sal_uLong DffPropSet::SanitizeEndPos(SvStream &rIn, sal_uLong nEndRecPos)
697 {
698 auto nStreamLen = rIn.Tell() + rIn.remainingSize();
699 if (nEndRecPos > nStreamLen)
700 {
701 SAL_WARN("filter.ms", "Parsing error: " << nStreamLen <<
702 " max end pos, but " << nEndRecPos << " claimed, truncating");
703 nEndRecPos = nStreamLen;
704 }
705 return nEndRecPos;
706 }
707
NotifyFreeObj(SdrObject * pObj)708 void ProcessData::NotifyFreeObj(SdrObject* pObj)
709 {
710 if (rPersistEntry.xSolverContainer)
711 {
712 for (auto & pPtr : rPersistEntry.xSolverContainer->aCList)
713 {
714 if (pPtr->pAObj == pObj)
715 pPtr->pAObj = nullptr;
716 if (pPtr->pBObj == pObj)
717 pPtr->pBObj = nullptr;
718 if (pPtr->pCObj == pObj)
719 pPtr->pCObj = nullptr;
720 }
721 }
722 }
723
724 /* ProcessObject is called from ImplSdPPTImport::ProcessObj to handle all application specific things,
725 such as the import of text, animation effects, header footer and placeholder.
726
727 The parameter pOriginalObj is the object as it was imported by our general escher import, it must either
728 be deleted or it can be returned to be inserted into the sdr page.
729 */
ProcessObj(SvStream & rSt,DffObjData & rObjData,SvxMSDffClientData & rClientData,tools::Rectangle & rTextRect,SdrObject * pOriginalObj)730 SdrObject* SdrEscherImport::ProcessObj( SvStream& rSt, DffObjData& rObjData, SvxMSDffClientData& rClientData, tools::Rectangle& rTextRect, SdrObject* pOriginalObj )
731 {
732 if ( dynamic_cast<const SdrObjCustomShape* >(pOriginalObj) != nullptr )
733 pOriginalObj->SetMergedItem( SdrTextFixedCellHeightItem( true ) );
734
735 // we are initializing our return value with the object that was imported by our escher import
736 SdrObject* pRet = pOriginalObj;
737
738 ProcessData& rData = static_cast<ProcessData&>(rClientData);
739 PptSlidePersistEntry& rPersistEntry = rData.rPersistEntry;
740
741 if ( ! (rObjData.nSpFlags & ShapeFlag::Group) ) // sj: #114758# ...
742 {
743 PptOEPlaceholderAtom aPlaceholderAtom;
744
745 if ( maShapeRecords.SeekToContent( rSt, DFF_msofbtClientData, SEEK_FROM_CURRENT_AND_RESTART ) )
746 {
747 sal_Int16 nHeaderFooterInstance = -1;
748 DffRecordHeader aClientDataHd;
749 auto nEndRecPos = SanitizeEndPos(rSt, maShapeRecords.Current()->GetRecEndFilePos());
750 while ( ( rSt.GetError() == ERRCODE_NONE ) && ( rSt.Tell() < nEndRecPos ) )
751 {
752 ReadDffRecordHeader( rSt, aClientDataHd );
753 switch ( aClientDataHd.nRecType )
754 {
755 // importing header/footer object from master page
756 case PPT_PST_OEPlaceholderAtom :
757 {
758 ReadPptOEPlaceholderAtom( rSt, aPlaceholderAtom );
759 if ( nHeaderFooterInstance == -1 )
760 {
761 switch ( aPlaceholderAtom.nPlaceholderId )
762 {
763 case PptPlaceholder::MASTERSLIDENUMBER : nHeaderFooterInstance++;
764 [[fallthrough]];
765 case PptPlaceholder::MASTERFOOTER : nHeaderFooterInstance++;
766 [[fallthrough]];
767 case PptPlaceholder::MASTERHEADER : nHeaderFooterInstance++;
768 [[fallthrough]];
769 case PptPlaceholder::MASTERDATE : nHeaderFooterInstance++; break;
770 default: break;
771
772 }
773 if ( ! ( nHeaderFooterInstance & 0xfffc ) ) // is this a valid instance ( 0->3 )
774 rPersistEntry.HeaderFooterOfs[ nHeaderFooterInstance ] = rObjData.rSpHd.GetRecBegFilePos();
775 }
776 }
777 break;
778
779 case PPT_PST_RecolorInfoAtom :
780 {
781 if ( auto pSdrGrafObj = dynamic_cast<SdrGrafObj* >(pRet) )
782 if ( pSdrGrafObj->HasGDIMetaFile() )
783 {
784 Graphic aGraphic( pSdrGrafObj->GetGraphic() );
785 RecolorGraphic( rSt, aClientDataHd.nRecLen, aGraphic );
786 pSdrGrafObj->SetGraphic( aGraphic );
787 }
788 }
789 break;
790 }
791 if (!aClientDataHd.SeekToEndOfRecord(rSt))
792 break;
793 }
794 }
795 if ( ( aPlaceholderAtom.nPlaceholderId == PptPlaceholder::NOTESSLIDEIMAGE ) && !rPersistEntry.bNotesMaster )
796 {
797 sal_uInt16 nPageNum = pSdrModel->GetPageCount();
798 if ( nPageNum > 0 )
799 nPageNum--;
800
801 // replacing the object which we will return with a SdrPageObj
802 SdrObject::Free( pRet );
803 pRet = new SdrPageObj(
804 *pSdrModel,
805 rObjData.aBoundRect,
806 pSdrModel->GetPage(nPageNum - 1));
807 }
808 else
809 {
810 // try to load some ppt text
811 PPTTextObj aTextObj( rSt, static_cast<SdrPowerPointImport&>(*this), rPersistEntry, &rObjData );
812 if ( aTextObj.Count() || aTextObj.GetOEPlaceHolderAtom() )
813 {
814 bool bVerticalText = false;
815 // and if the text object is not empty, it must be applied to pRet, the object we
816 // initially got from our escher import
817 Degree100 nTextRotationAngle(0);
818 if ( IsProperty( DFF_Prop_txflTextFlow ) )
819 {
820 auto eTextFlow = GetPropertyValue(DFF_Prop_txflTextFlow, 0) & 0xFFFF;
821 switch( eTextFlow )
822 {
823 case mso_txflBtoT : // Bottom to Top non-@
824 nTextRotationAngle += 9000_deg100;
825 break;
826 case mso_txflTtoBA : /* #68110# */ // Top to Bottom @-font
827 case mso_txflTtoBN : // Top to Bottom non-@
828 case mso_txflVertN : // Vertical, non-@, top to bottom
829 bVerticalText = !bVerticalText; // nTextRotationAngle += 27000;
830 break;
831 // case mso_txflHorzN : // Horizontal non-@, normal
832 // case mso_txflHorzA : // Horizontal @-font, normal
833 default: break;
834 }
835 }
836 sal_Int32 nFontDirection = GetPropertyValue( DFF_Prop_cdirFont, mso_cdir0 );
837 if ( ( nFontDirection == 1 ) || ( nFontDirection == 3 ) )
838 {
839 bVerticalText = !bVerticalText;
840 }
841 const bool bFail = o3tl::checked_multiply<sal_Int32>(nFontDirection, 9000, nFontDirection);
842 if (!bFail)
843 nTextRotationAngle -= Degree100(nFontDirection);
844 else
845 SAL_WARN("filter.ms", "Parsing error: bad fontdirection: " << nFontDirection);
846 aTextObj.SetVertical( bVerticalText );
847 if ( pRet )
848 {
849 bool bDeleteSource = aTextObj.GetOEPlaceHolderAtom() != nullptr;
850 if ( bDeleteSource && dynamic_cast<const SdrGrafObj* >(pRet) == nullptr // we are not allowed to get
851 && dynamic_cast<const SdrObjGroup* >(pRet) == nullptr // grouped placeholder objects
852 && dynamic_cast<const SdrOle2Obj* >(pRet) == nullptr )
853 SdrObject::Free( pRet );
854 }
855 sal_uInt32 nTextFlags = aTextObj.GetTextFlags();
856 sal_Int32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft, 25 * 3600 ); // 0.25 cm (emu)
857 sal_Int32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight, 25 * 3600 ); // 0.25 cm (emu)
858 sal_Int32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop, 13 * 3600 ); // 0.13 cm (emu)
859 sal_Int32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom, 13 * 3600 );
860 ScaleEmu( nTextLeft );
861 ScaleEmu( nTextRight );
862 ScaleEmu( nTextTop );
863 ScaleEmu( nTextBottom );
864
865 sal_Int32 nMinFrameWidth = 0;
866 sal_Int32 nMinFrameHeight = 0;
867 bool bAutoGrowWidth, bAutoGrowHeight;
868
869 SdrTextVertAdjust eTVA;
870 SdrTextHorzAdjust eTHA;
871
872 nTextFlags &= PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT
873 | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK;
874
875 if ( bVerticalText )
876 {
877 eTVA = SDRTEXTVERTADJUST_BLOCK;
878 eTHA = SDRTEXTHORZADJUST_CENTER;
879
880 // read text anchor
881 auto eTextAnchor = GetPropertyValue(DFF_Prop_anchorText, mso_anchorTop);
882
883 switch( eTextAnchor )
884 {
885 case mso_anchorTop:
886 case mso_anchorTopCentered:
887 case mso_anchorTopBaseline:
888 case mso_anchorTopCenteredBaseline:
889 eTHA = SDRTEXTHORZADJUST_RIGHT;
890 break;
891
892 case mso_anchorMiddle :
893 case mso_anchorMiddleCentered:
894 eTHA = SDRTEXTHORZADJUST_CENTER;
895 break;
896
897 case mso_anchorBottom:
898 case mso_anchorBottomCentered:
899 case mso_anchorBottomBaseline:
900 case mso_anchorBottomCenteredBaseline:
901 eTHA = SDRTEXTHORZADJUST_LEFT;
902 break;
903 }
904 switch ( eTextAnchor )
905 {
906 case mso_anchorTopCentered :
907 case mso_anchorMiddleCentered :
908 case mso_anchorBottomCentered :
909 case mso_anchorTopCenteredBaseline:
910 case mso_anchorBottomCenteredBaseline:
911 {
912 // check if it is sensible to use the centered alignment
913 const sal_uInt32 nMask = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK;
914 switch (nTextFlags & nMask)
915 {
916 case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT:
917 case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER:
918 case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT:
919 case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK:
920 eTVA = SDRTEXTVERTADJUST_CENTER; // If the textobject has only one type of alignment, then the text has not to be displayed using the full width;
921 break;
922 }
923 break;
924 }
925 default:
926 break;
927 }
928 nMinFrameWidth = rTextRect.GetWidth() - ( nTextLeft + nTextRight );
929 }
930 else
931 {
932 eTVA = SDRTEXTVERTADJUST_CENTER;
933 eTHA = SDRTEXTHORZADJUST_BLOCK;
934
935 // read text anchor
936 auto eTextAnchor = GetPropertyValue(DFF_Prop_anchorText, mso_anchorTop);
937
938 switch( eTextAnchor )
939 {
940 case mso_anchorTop:
941 case mso_anchorTopCentered:
942 case mso_anchorTopBaseline:
943 case mso_anchorTopCenteredBaseline:
944 eTVA = SDRTEXTVERTADJUST_TOP;
945 break;
946
947 case mso_anchorMiddle :
948 case mso_anchorMiddleCentered:
949 eTVA = SDRTEXTVERTADJUST_CENTER;
950 break;
951
952 case mso_anchorBottom:
953 case mso_anchorBottomCentered:
954 case mso_anchorBottomBaseline:
955 case mso_anchorBottomCenteredBaseline:
956 eTVA = SDRTEXTVERTADJUST_BOTTOM;
957 break;
958 }
959 switch ( eTextAnchor )
960 {
961 case mso_anchorTopCentered :
962 case mso_anchorMiddleCentered :
963 case mso_anchorBottomCentered :
964 case mso_anchorTopCenteredBaseline:
965 case mso_anchorBottomCenteredBaseline:
966 {
967 // check if it is sensible to use the centered alignment
968 const sal_uInt32 nMask = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK;
969 switch (nTextFlags & nMask)
970 {
971 case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT:
972 case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER:
973 case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT:
974 case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK:
975 eTHA = SDRTEXTHORZADJUST_CENTER; // If the textobject has only one type of alignment, then the text has not to be displayed using the full width;
976 break;
977 }
978 break;
979 }
980 default:
981 break;
982 }
983 nMinFrameHeight = rTextRect.GetHeight() - ( nTextTop + nTextBottom );
984 }
985
986 SdrObjKind eTextKind = OBJ_RECT;
987 if ( ( aPlaceholderAtom.nPlaceholderId == PptPlaceholder::NOTESSLIDEIMAGE )
988 || ( aPlaceholderAtom.nPlaceholderId == PptPlaceholder::MASTERNOTESSLIDEIMAGE ) )
989 {
990 aTextObj.SetInstance( TSS_Type::Notes );
991 eTextKind = OBJ_TITLETEXT;
992 }
993 else if ( ( aPlaceholderAtom.nPlaceholderId == PptPlaceholder::MASTERNOTESBODYIMAGE )
994 || ( aPlaceholderAtom.nPlaceholderId == PptPlaceholder::NOTESBODY ) )
995 {
996 aTextObj.SetInstance( TSS_Type::Notes );
997 eTextKind = OBJ_TEXT;
998 }
999
1000 TSS_Type nDestinationInstance = aTextObj.GetInstance();
1001 if ( rPersistEntry.ePageKind == PPT_MASTERPAGE )
1002 {
1003 if ( !rPersistEntry.pPresentationObjects )
1004 {
1005 rPersistEntry.pPresentationObjects.reset( new sal_uInt32[ PPT_STYLESHEETENTRIES ] );
1006 memset( rPersistEntry.pPresentationObjects.get(), 0, PPT_STYLESHEETENTRIES * 4 );
1007 }
1008 if ( !rPersistEntry.pPresentationObjects[ static_cast<int>(nDestinationInstance) ] )
1009 rPersistEntry.pPresentationObjects[ static_cast<int>(nDestinationInstance) ] = rObjData.rSpHd.GetRecBegFilePos();
1010 }
1011 switch ( nDestinationInstance )
1012 {
1013 case TSS_Type::PageTitle :
1014 case TSS_Type::Title :
1015 {
1016 if ( GetSlideLayoutAtom()->eLayout == PptSlideLayout::TITLEMASTERSLIDE )
1017 nDestinationInstance = TSS_Type::Title;
1018 else
1019 nDestinationInstance = TSS_Type::PageTitle;
1020 }
1021 break;
1022 case TSS_Type::Body :
1023 case TSS_Type::HalfBody :
1024 case TSS_Type::QuarterBody :
1025 nDestinationInstance = TSS_Type::Body;
1026 break;
1027 default: break;
1028 }
1029 aTextObj.SetDestinationInstance( nDestinationInstance );
1030
1031 bool bAutoFit = false; // auto-scale text into shape box
1032 switch ( aTextObj.GetInstance() )
1033 {
1034 case TSS_Type::PageTitle :
1035 case TSS_Type::Title : eTextKind = OBJ_TITLETEXT; break;
1036 case TSS_Type::Subtitle : eTextKind = OBJ_TEXT; break;
1037 case TSS_Type::Body :
1038 case TSS_Type::HalfBody :
1039 case TSS_Type::QuarterBody : eTextKind = OBJ_OUTLINETEXT; bAutoFit = true; break;
1040 default: break;
1041 }
1042 if ( aTextObj.GetDestinationInstance() != TSS_Type::TextInShape )
1043 {
1044 if ( !aTextObj.GetOEPlaceHolderAtom() || aTextObj.GetOEPlaceHolderAtom()->nPlaceholderId == PptPlaceholder::NONE )
1045 {
1046 aTextObj.SetDestinationInstance( TSS_Type::TextInShape );
1047 eTextKind = OBJ_RECT;
1048 }
1049 }
1050 SdrObject* pTObj = nullptr;
1051 bool bWordWrap = GetPropertyValue(DFF_Prop_WrapText, mso_wrapSquare) != mso_wrapNone;
1052 bool bFitShapeToText = ( GetPropertyValue( DFF_Prop_FitTextToShape, 0 ) & 2 ) != 0;
1053
1054 if ( dynamic_cast<const SdrObjCustomShape* >(pRet) != nullptr && ( eTextKind == OBJ_RECT ) )
1055 {
1056 bAutoGrowHeight = bFitShapeToText;
1057 bAutoGrowWidth = !bWordWrap;
1058 pTObj = pRet;
1059 pRet = nullptr;
1060 }
1061 else
1062 {
1063 if ( dynamic_cast<const SdrObjCustomShape* >(pRet) != nullptr )
1064 {
1065 SdrObject::Free( pRet );
1066 pRet = nullptr;
1067 }
1068 pTObj = new SdrRectObj(
1069 *pSdrModel,
1070 eTextKind != OBJ_RECT ? eTextKind : OBJ_TEXT);
1071 SfxItemSet aSet( pSdrModel->GetItemPool() );
1072 if ( !pRet )
1073 ApplyAttributes( rSt, aSet, rObjData );
1074 pTObj->SetMergedItemSet( aSet );
1075 if ( pRet )
1076 {
1077 pTObj->SetMergedItem( XLineStyleItem( drawing::LineStyle_NONE ) );
1078 pTObj->SetMergedItem( XFillStyleItem( drawing::FillStyle_NONE ) );
1079 }
1080 if ( bVerticalText )
1081 {
1082 bAutoGrowWidth = bFitShapeToText;
1083 bAutoGrowHeight = false;
1084 }
1085 else
1086 {
1087 bAutoGrowWidth = false;
1088
1089 // #119885# re-activating bFitShapeToText here, could not find deeper explanations
1090 // for it (it was from 2005). Keeping the old comment here for reference
1091 // old comment: // bFitShapeToText; can't be used, because we cut the text if it is too height,
1092 bAutoGrowHeight = bFitShapeToText;
1093 }
1094 }
1095 pTObj->SetMergedItem( SvxFrameDirectionItem( bVerticalText ? SvxFrameDirection::Vertical_RL_TB : SvxFrameDirection::Horizontal_LR_TB, EE_PARA_WRITINGDIR ) );
1096
1097 //Autofit text only if there is no auto grow height and width
1098 //See fdo#41245
1099 if (bAutoFit && !bAutoGrowHeight && !bAutoGrowWidth)
1100 {
1101 pTObj->SetMergedItem( SdrTextFitToSizeTypeItem(drawing::TextFitToSizeType_AUTOFIT) );
1102 }
1103
1104 if ( dynamic_cast<const SdrObjCustomShape* >(pTObj) == nullptr )
1105 {
1106 pTObj->SetMergedItem( makeSdrTextAutoGrowWidthItem( bAutoGrowWidth ) );
1107 pTObj->SetMergedItem( makeSdrTextAutoGrowHeightItem( bAutoGrowHeight ) );
1108 }
1109 else
1110 {
1111 pTObj->SetMergedItem( makeSdrTextWordWrapItem( bWordWrap ) );
1112 pTObj->SetMergedItem( makeSdrTextAutoGrowHeightItem( bFitShapeToText ) );
1113 }
1114
1115 pTObj->SetMergedItem( SdrTextVertAdjustItem( eTVA ) );
1116 pTObj->SetMergedItem( SdrTextHorzAdjustItem( eTHA ) );
1117
1118 if ( nMinFrameHeight < 0 )
1119 nMinFrameHeight = 0;
1120 if ( dynamic_cast<const SdrObjCustomShape* >(pTObj) == nullptr )
1121 pTObj->SetMergedItem( makeSdrTextMinFrameHeightItem( nMinFrameHeight ) );
1122
1123 if ( nMinFrameWidth < 0 )
1124 nMinFrameWidth = 0;
1125 if ( dynamic_cast<const SdrObjCustomShape* >(pTObj) == nullptr )
1126 pTObj->SetMergedItem( makeSdrTextMinFrameWidthItem( nMinFrameWidth ) );
1127
1128 // set margins at the borders of the textbox
1129 pTObj->SetMergedItem( makeSdrTextLeftDistItem( nTextLeft ) );
1130 pTObj->SetMergedItem( makeSdrTextRightDistItem( nTextRight ) );
1131 pTObj->SetMergedItem( makeSdrTextUpperDistItem( nTextTop ) );
1132 pTObj->SetMergedItem( makeSdrTextLowerDistItem( nTextBottom ) );
1133 pTObj->SetMergedItem( SdrTextFixedCellHeightItem( true ) );
1134
1135 if ( dynamic_cast<const SdrObjCustomShape* >(pTObj) == nullptr )
1136 pTObj->SetSnapRect( rTextRect );
1137 pTObj = ReadObjText( &aTextObj, pTObj, rData.pPage );
1138
1139 if ( pTObj )
1140 {
1141 /* check if our new snaprect makes trouble,
1142 because we do not display the ADJUST_BLOCK
1143 properly if the textsize is bigger than the
1144 snaprect of the object. Then we will use
1145 ADJUST_CENTER instead of ADJUST_BLOCK.
1146 */
1147 if ( dynamic_cast<const SdrObjCustomShape* >(pTObj) == nullptr && !bFitShapeToText && !bWordWrap )
1148 {
1149 SdrTextObj* pText = dynamic_cast<SdrTextObj*>( pTObj );
1150 if ( pText )
1151 {
1152 if ( bVerticalText )
1153 {
1154 if ( eTVA == SDRTEXTVERTADJUST_BLOCK )
1155 {
1156 Size aTextSize( pText->GetTextSize() );
1157 aTextSize.AdjustWidth(nTextLeft + nTextRight );
1158 aTextSize.AdjustHeight(nTextTop + nTextBottom );
1159 if ( rTextRect.GetHeight() < aTextSize.Height() )
1160 pTObj->SetMergedItem( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER ) );
1161 }
1162 }
1163 else
1164 {
1165 if ( eTHA == SDRTEXTHORZADJUST_BLOCK )
1166 {
1167 Size aTextSize( pText->GetTextSize() );
1168 aTextSize.AdjustWidth(nTextLeft + nTextRight );
1169 aTextSize.AdjustHeight(nTextTop + nTextBottom );
1170 if ( rTextRect.GetWidth() < aTextSize.Width() )
1171 pTObj->SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_CENTER ) );
1172 }
1173 }
1174 }
1175 }
1176 // rotate text with shape?
1177 Degree100 nAngle = ( rObjData.nSpFlags & ShapeFlag::FlipV ) ? -mnFix16Angle : mnFix16Angle; // #72116# vertical flip -> rotate by using the other way
1178 nAngle += nTextRotationAngle;
1179
1180 if ( dynamic_cast< const SdrObjCustomShape* >(pTObj) == nullptr )
1181 {
1182 if ( rObjData.nSpFlags & ShapeFlag::FlipV )
1183 {
1184 double a = 18000 * F_PI18000;
1185 pTObj->Rotate( rTextRect.Center(), 18000_deg100, sin( a ), cos( a ) );
1186 }
1187 if ( rObjData.nSpFlags & ShapeFlag::FlipH )
1188 nAngle = 36000_deg100 - nAngle;
1189 if ( nAngle )
1190 pTObj->NbcRotate( rObjData.aBoundRect.Center(), nAngle );
1191 }
1192 if ( pRet )
1193 {
1194 SdrObject* pGroup = new SdrObjGroup(*pSdrModel);
1195 pGroup->GetSubList()->NbcInsertObject( pRet );
1196 pGroup->GetSubList()->NbcInsertObject( pTObj );
1197 pRet = pGroup;
1198 }
1199 else
1200 pRet = pTObj;
1201 }
1202 }
1203 }
1204 }
1205 else
1206 {
1207 if ( maShapeRecords.SeekToContent( rSt, DFF_msofbtUDefProp, SEEK_FROM_CURRENT_AND_RESTART ) )
1208 {
1209 maShapeRecords.Current()->SeekToBegOfRecord( rSt );
1210 DffPropertyReader aSecPropSet( *this );
1211 aSecPropSet.ReadPropSet( rSt, &rClientData );
1212 sal_Int32 nTableProperties = aSecPropSet.GetPropertyValue( DFF_Prop_tableProperties, 0 );
1213 if ( nTableProperties & 3 )
1214 {
1215 if ( aSecPropSet.SeekToContent( DFF_Prop_tableRowProperties, rSt ) )
1216 {
1217 sal_Int16 i, nReadRowCount = 0;
1218 rSt.ReadInt16( nReadRowCount ).ReadInt16( i ).ReadInt16( i );
1219 if (nReadRowCount > 0)
1220 {
1221 const size_t nMinRecordSize = 4;
1222 const size_t nMaxRecords = rSt.remainingSize() / nMinRecordSize;
1223
1224 auto nRowCount = o3tl::make_unsigned(nReadRowCount);
1225 if (nRowCount > nMaxRecords)
1226 {
1227 SAL_WARN("filter.ms", "Parsing error: " << nMaxRecords <<
1228 " max possible entries, but " << nRowCount << " claimed, truncating");
1229 nRowCount = nMaxRecords;
1230 }
1231 if (nRowCount > 0)
1232 {
1233 std::unique_ptr<sal_uInt32[]> pTableArry(new sal_uInt32[ nRowCount + 2 ]);
1234 pTableArry[ 0 ] = nTableProperties;
1235 pTableArry[ 1 ] = nRowCount;
1236 for (decltype(nRowCount) nRow = 0; nRow < nRowCount; ++nRow)
1237 rSt.ReadUInt32(pTableArry[nRow + 2]);
1238 rData.pTableRowProperties = std::move(pTableArry);
1239 }
1240 }
1241 }
1242 }
1243 }
1244 }
1245 if ( pRet ) // sj: #i38501#, and taking care of connections to group objects
1246 {
1247 if ( rObjData.nSpFlags & ShapeFlag::Background )
1248 {
1249 pRet->NbcSetSnapRect( tools::Rectangle( Point(), rData.pPage.page->GetSize() ) ); // set size
1250 }
1251 if (rPersistEntry.xSolverContainer)
1252 {
1253 for (auto & pPtr : rPersistEntry.xSolverContainer->aCList)
1254 {
1255 if ( rObjData.nShapeId == pPtr->nShapeC )
1256 pPtr->pCObj = pRet;
1257 else
1258 {
1259 SdrObject* pConnectObj = pRet;
1260 if ( pOriginalObj && dynamic_cast< const SdrObjGroup* >(pRet) != nullptr )
1261 { /* check if the original object from the escherimport is part of the group object,
1262 if this is the case, we will use the original object to connect to */
1263 SdrObjListIter aIter( *pRet, SdrIterMode::DeepWithGroups );
1264 while( aIter.IsMore() )
1265 {
1266 SdrObject* pPartObj = aIter.Next();
1267 if ( pPartObj == pOriginalObj )
1268 {
1269 pConnectObj = pPartObj;
1270 break;
1271 }
1272 }
1273 }
1274 if ( rObjData.nShapeId == pPtr->nShapeA )
1275 {
1276 pPtr->pAObj = pConnectObj;
1277 pPtr->nSpFlagsA = rObjData.nSpFlags;
1278 }
1279 if ( rObjData.nShapeId == pPtr->nShapeB )
1280 {
1281 pPtr->pBObj = pConnectObj;
1282 pPtr->nSpFlagsB = rObjData.nSpFlags;
1283 }
1284 }
1285 }
1286 }
1287 if ( rPersistEntry.ePageKind == PPT_MASTERPAGE )
1288 { // maybe the escher clusterlist is not correct, but we have to got the right page by using the
1289 // spMaster property, so we are patching the table
1290 if ( rPersistEntry.nDrawingDgId != 0xffffffff )
1291 {
1292 sal_uInt32 nSec = ( rObjData.nShapeId >> 10 ) - 1;
1293 if ( !maFidcls.empty() && ( nSec < mnIdClusters ) )
1294 maFidcls[ nSec ].dgid = rPersistEntry.nDrawingDgId; // insert the correct drawing id;
1295 }
1296 }
1297 if ( GetPropertyValue( DFF_Prop_fNoFillHitTest, 0 ) & 0x10 )
1298 {
1299 if (GetPropertyValue(DFF_Prop_fillType, mso_fillSolid) == mso_fillBackground)
1300 {
1301 rData.aBackgroundColoredObjects.push_back( pRet );
1302 }
1303 }
1304 }
1305 return pRet;
1306 }
1307
SdrPowerPointImport(PowerPointImportParam & rParam,const OUString & rBaseURL)1308 SdrPowerPointImport::SdrPowerPointImport( PowerPointImportParam& rParam, const OUString& rBaseURL ) :
1309 SdrEscherImport ( rParam, rBaseURL ),
1310 m_bOk ( rStCtrl.GetErrorCode() == ERRCODE_NONE ),
1311 m_nPersistPtrCnt ( 0 ),
1312 m_pDefaultSheet ( nullptr ),
1313 m_nCurrentPageNum ( 0 ),
1314 m_nDocStreamPos ( 0 ),
1315 m_nPageColorsNum ( 0xFFFF ),
1316 m_ePageColorsKind ( PPT_MASTERPAGE ),
1317 m_eCurrentPageKind ( PPT_MASTERPAGE )
1318 {
1319 if ( m_bOk )
1320 {
1321 rStCtrl.Seek( STREAM_SEEK_TO_END );
1322 nStreamLen = rStCtrl.Tell();
1323
1324 // try to allocate the UserEditAtom via CurrentUserAtom
1325 sal_uInt32 nCurrentUserEdit = rParam.aCurrentUserAtom.nCurrentUserEdit;
1326 if (nCurrentUserEdit && checkSeek(rStCtrl, nCurrentUserEdit))
1327 {
1328 ReadPptUserEditAtom( rStCtrl, m_aUserEditAtom );
1329 }
1330 if ( !m_aUserEditAtom.nOffsetPersistDirectory )
1331 { // if there is no UserEditAtom try to search the last one
1332
1333 rStCtrl.Seek( 0 );
1334 DffRecordManager aPptRecManager; // contains all first level container and atoms
1335 aPptRecManager.Consume( rStCtrl, nStreamLen );
1336 DffRecordHeader* pHd;
1337 for ( pHd = aPptRecManager.Last(); pHd; pHd = aPptRecManager.Prev() )
1338 {
1339 if ( pHd->nRecType == PPT_PST_UserEditAtom )
1340 {
1341 pHd->SeekToBegOfRecord( rStCtrl );
1342 ReadPptUserEditAtom( rStCtrl, m_aUserEditAtom );
1343 break;
1344 }
1345 }
1346 if ( !pHd )
1347 m_bOk = false;
1348 }
1349 }
1350 if ( rStCtrl.GetError() != ERRCODE_NONE )
1351 m_bOk = false;
1352
1353 if ( m_bOk )
1354 {
1355 m_nPersistPtrCnt = m_aUserEditAtom.nMaxPersistWritten + 1;
1356 if ( ( m_nPersistPtrCnt >> 2 ) > nStreamLen ) // sj: at least m_nPersistPtrCnt is not allowed to be greater than filesize
1357 m_bOk = false; // (it should not be greater than the PPT_PST_PersistPtrIncrementalBlock, but
1358 // we are reading this block later, so we do not have access yet)
1359
1360 if ( m_bOk && ( m_nPersistPtrCnt < ( SAL_MAX_UINT32 / sizeof( sal_uInt32 ) ) -1 ) )
1361 m_pPersistPtr.reset( new (std::nothrow) sal_uInt32[ m_nPersistPtrCnt + 1 ] );
1362 if ( !m_pPersistPtr )
1363 m_bOk = false;
1364 if ( m_bOk )
1365 {
1366 memset( m_pPersistPtr.get(), 0x00, (m_nPersistPtrCnt+1) * sizeof(sal_uInt32) );
1367
1368 // SJ: new search mechanism from bottom to top (Issue 21122)
1369 PptUserEditAtom aCurrentEditAtom( m_aUserEditAtom );
1370 sal_uInt32 nCurrentEditAtomStrmPos = aCurrentEditAtom.aHd.GetRecEndFilePos();
1371 while( nCurrentEditAtomStrmPos )
1372 {
1373 sal_uInt32 nPersistIncPos = aCurrentEditAtom.nOffsetPersistDirectory;
1374 if (nPersistIncPos && checkSeek(rStCtrl, nPersistIncPos))
1375 {
1376 DffRecordHeader aPersistHd;
1377 ReadDffRecordHeader( rStCtrl, aPersistHd );
1378 if ( aPersistHd.nRecType == PPT_PST_PersistPtrIncrementalBlock )
1379 {
1380 sal_uLong nPibLen = aPersistHd.GetRecEndFilePos();
1381 while (m_bOk && rStCtrl.good() && (rStCtrl.Tell() < nPibLen))
1382 {
1383 sal_uInt32 nOfs(0);
1384 rStCtrl.ReadUInt32( nOfs );
1385 sal_uInt32 nCnt = nOfs;
1386 nOfs &= 0x000FFFFF;
1387 nCnt >>= 20;
1388 while (m_bOk && rStCtrl.good() && (nCnt > 0) && (nOfs <= m_nPersistPtrCnt))
1389 {
1390 sal_uInt32 nPt(0);
1391 rStCtrl.ReadUInt32( nPt );
1392 if ( !m_pPersistPtr[ nOfs ] )
1393 {
1394 m_pPersistPtr[ nOfs ] = nPt;
1395 if ( m_pPersistPtr[ nOfs ] > nStreamLen )
1396 {
1397 m_bOk = false;
1398 OSL_FAIL("SdrPowerPointImport::Ctor(): Invalid Entry in Persist-Directory!");
1399 }
1400 }
1401 nCnt--;
1402 nOfs++;
1403 }
1404 if ( m_bOk && nCnt > 0 )
1405 {
1406 OSL_FAIL("SdrPowerPointImport::Ctor(): Not all entries of Persist-Directory read!");
1407 m_bOk = false;
1408 }
1409 }
1410 }
1411 }
1412 nCurrentEditAtomStrmPos = aCurrentEditAtom.nOffsetLastEdit < nCurrentEditAtomStrmPos ? aCurrentEditAtom.nOffsetLastEdit : 0;
1413 if (nCurrentEditAtomStrmPos && checkSeek(rStCtrl, nCurrentEditAtomStrmPos))
1414 {
1415 ReadPptUserEditAtom( rStCtrl, aCurrentEditAtom );
1416 }
1417 }
1418 }
1419 }
1420 if ( rStCtrl.GetError() != ERRCODE_NONE )
1421 m_bOk = false;
1422 if ( m_bOk )
1423 { // check Document PersistEntry
1424 m_nDocStreamPos = m_aUserEditAtom.nDocumentRef;
1425 if ( m_nDocStreamPos > m_nPersistPtrCnt )
1426 {
1427 OSL_FAIL("SdrPowerPointImport::Ctor(): m_aUserEditAtom.nDocumentRef invalid!");
1428 m_bOk = false;
1429 }
1430 }
1431 if ( m_bOk )
1432 { // check Document FilePos
1433 m_nDocStreamPos = m_pPersistPtr[ m_nDocStreamPos ];
1434 if ( m_nDocStreamPos >= nStreamLen )
1435 {
1436 OSL_FAIL("SdrPowerPointImport::Ctor(): m_nDocStreamPos >= nStreamLen!");
1437 m_bOk = false;
1438 }
1439 }
1440 if ( m_bOk )
1441 {
1442 rStCtrl.Seek( m_nDocStreamPos );
1443 aDocRecManager.Consume( rStCtrl );
1444
1445 DffRecordHeader aDocHd;
1446 ReadDffRecordHeader( rStCtrl, aDocHd );
1447 // read DocumentAtom
1448 DffRecordHeader aDocAtomHd;
1449 ReadDffRecordHeader( rStCtrl, aDocAtomHd );
1450 if ( aDocHd.nRecType == PPT_PST_Document && aDocAtomHd.nRecType == PPT_PST_DocumentAtom )
1451 {
1452 aDocAtomHd.SeekToBegOfRecord( rStCtrl );
1453 ReadPptDocumentAtom( rStCtrl, aDocAtom );
1454 }
1455 else
1456 m_bOk = false;
1457
1458 if ( m_bOk )
1459 {
1460 if (!m_pFonts)
1461 ReadFontCollection();
1462
1463 // reading TxPF, TxSI
1464 PPTTextParagraphStyleAtomInterpreter aTxPFStyle;
1465 PPTTextSpecInfoAtomInterpreter aTxSIStyle; // styles (default language setting ... )
1466
1467 DffRecordHeader* pEnvHd = aDocRecManager.GetRecordHeader( PPT_PST_Environment );
1468 if ( pEnvHd )
1469 {
1470 pEnvHd->SeekToContent( rStCtrl );
1471 DffRecordHeader aTxPFStyleRecHd;
1472 if ( SeekToRec( rStCtrl, PPT_PST_TxPFStyleAtom, pEnvHd->GetRecEndFilePos(), &aTxPFStyleRecHd ) )
1473 aTxPFStyle.Read( rStCtrl, aTxPFStyleRecHd );
1474
1475 pEnvHd->SeekToContent( rStCtrl );
1476 DffRecordHeader aTxSIStyleRecHd;
1477 if ( SeekToRec( rStCtrl, PPT_PST_TxSIStyleAtom, pEnvHd->GetRecEndFilePos(), &aTxSIStyleRecHd ) )
1478 {
1479 aTxSIStyle.Read( rStCtrl, aTxSIStyleRecHd, PPT_PST_TxSIStyleAtom );
1480 #ifdef DBG_UTIL
1481 if ( !aTxSIStyle.bValid )
1482 {
1483 if (!(rImportParam.nImportFlags & PPT_IMPORTFLAGS_NO_TEXT_ASSERT ))
1484 {
1485 OSL_FAIL( "SdrTextSpecInfoAtomInterpreter::Ctor(): parsing error, this document needs to be analysed (SJ)" );
1486 }
1487 }
1488 #endif
1489 }
1490 }
1491
1492 // TODO:: PPT_PST_TxPFStyleAtom
1493
1494 // read SlidePersists
1495 m_pMasterPages.reset( new PptSlidePersistList );
1496 m_pSlidePages.reset( new PptSlidePersistList );
1497 m_pNotePages.reset( new PptSlidePersistList );
1498
1499 // now always creating the handout page, it will be the first in our masterpage list
1500 std::unique_ptr<PptSlidePersistEntry> pE(new PptSlidePersistEntry);
1501 pE->aPersistAtom.nPsrReference = aDocAtom.nHandoutMasterPersist;
1502 pE->bHandoutMaster = true;
1503 if ( !aDocAtom.nHandoutMasterPersist )
1504 pE->bStarDrawFiller = true; // this is a dummy master page
1505 m_pMasterPages->insert(m_pMasterPages->begin(), std::move(pE));
1506
1507 DffRecordHeader* pSlideListWithTextHd = aDocRecManager.GetRecordHeader( PPT_PST_SlideListWithText );
1508 PptSlidePersistEntry* pPreviousPersist = nullptr;
1509 DffRecordHeader* pSlideListHd = aDocRecManager.GetRecordHeader(PPT_PST_List);
1510 sal_uLong nPSTList = 0;
1511 if (pSlideListHd) nPSTList = pSlideListHd->GetRecBegFilePos();
1512 sal_uInt16 nRealPageNum = 0;
1513 // Normal PPT document has order of Master slides - Presentation slides - Note slides
1514 // for document with the order of Master slides - Note slides - Presentation slides
1515 // we need to swap the later two sections
1516 bool notePresentationSwap = false;
1517 for (sal_uInt16 nPageListNum = 0;
1518 pSlideListWithTextHd && nPageListNum < 3; ++nPageListNum)
1519 {
1520 pSlideListWithTextHd->SeekToContent( rStCtrl );
1521 PptSlidePersistList* pPageList = nullptr;
1522 sal_uInt32 nSlideListWithTextHdEndOffset = pSlideListWithTextHd->GetRecEndFilePos();
1523 nRealPageNum = nPageListNum;
1524 while ( SeekToRec( rStCtrl, PPT_PST_SlidePersistAtom, nSlideListWithTextHdEndOffset ) )
1525 {
1526 if ( pPreviousPersist )
1527 pPreviousPersist->nSlidePersistEndOffset = rStCtrl.Tell();
1528 std::unique_ptr<PptSlidePersistEntry> pE2(new PptSlidePersistEntry);
1529 ReadPptSlidePersistAtom( rStCtrl, pE2->aPersistAtom );
1530 pE2->nSlidePersistStartOffset = rStCtrl.Tell();
1531 // Note/Presentation section swap
1532 if (nPageListNum == 1 && pE2->nSlidePersistStartOffset < nPSTList)
1533 {
1534 notePresentationSwap = true;
1535 }
1536 if (notePresentationSwap)
1537 {
1538 if (nPageListNum == 1) nRealPageNum = 2;
1539 else if (nPageListNum == 2) nRealPageNum = 1;
1540 }
1541
1542 pE2->ePageKind = PptPageKind(nRealPageNum);
1543 pPreviousPersist = pE2.get();
1544 if (!pPageList)
1545 {
1546 pPageList = GetPageList(PptPageKind(nRealPageNum));
1547 }
1548 pPageList->push_back(std::move(pE2));
1549 }
1550 if ( pPreviousPersist )
1551 pPreviousPersist->nSlidePersistEndOffset = nSlideListWithTextHdEndOffset;
1552 pSlideListWithTextHd = aDocRecManager.GetRecordHeader( PPT_PST_SlideListWithText, SEEK_FROM_CURRENT );
1553 }
1554
1555 // we will ensure that there is at least one master page
1556 if (m_pMasterPages->size() == 1) // -> there is only a handout page available
1557 {
1558 std::unique_ptr<PptSlidePersistEntry> pE2(new PptSlidePersistEntry);
1559 pE2->bStarDrawFiller = true; // this is a dummy master page
1560 m_pMasterPages->insert(m_pMasterPages->begin() + 1, std::move(pE2));
1561 }
1562
1563 // now we will insert at least one notes master for each master page
1564 sal_uInt16 nMasterPage;
1565 sal_uInt16 nMasterPages = m_pMasterPages->size() - 1;
1566 for ( nMasterPage = 0; nMasterPage < nMasterPages; nMasterPage++ )
1567 {
1568 std::unique_ptr<PptSlidePersistEntry> pE2(new PptSlidePersistEntry);
1569 pE2->bNotesMaster = true;
1570 pE2->bStarDrawFiller = true; // this is a dummy master page
1571 if ( !nMasterPage && aDocAtom.nNotesMasterPersist )
1572 { // special treatment for the first notes master
1573 pE2->aPersistAtom.nPsrReference = aDocAtom.nNotesMasterPersist;
1574 pE2->bStarDrawFiller = false; // this is a dummy master page
1575 }
1576 m_pMasterPages->insert(m_pMasterPages->begin() + ((nMasterPage + 1) << 1), std::move(pE2));
1577 }
1578
1579 // read for each page the SlideAtom respectively the NotesAtom if it exists
1580 for (sal_uInt16 nPageListNum = 0; nPageListNum < 3; ++nPageListNum)
1581 {
1582 PptSlidePersistList* pPageList = GetPageList( PptPageKind( nPageListNum ) );
1583 for ( size_t nPageNum = 0; nPageNum < pPageList->size(); nPageNum++ )
1584 {
1585 PptSlidePersistEntry& rE2 = (*pPageList)[ nPageNum ];
1586 sal_uLong nPersist = rE2.aPersistAtom.nPsrReference;
1587 if ( ( nPersist > 0 ) && ( nPersist < m_nPersistPtrCnt ) )
1588 {
1589 sal_uLong nFPos = m_pPersistPtr[ nPersist ];
1590 if ( nFPos < nStreamLen )
1591 {
1592 rStCtrl.Seek( nFPos );
1593 DffRecordHeader aSlideHd;
1594 ReadDffRecordHeader( rStCtrl, aSlideHd );
1595 if ( SeekToRec( rStCtrl, PPT_PST_SlideAtom, aSlideHd.GetRecEndFilePos() ) )
1596 ReadPptSlideAtom( rStCtrl, rE2.aSlideAtom );
1597 else if ( SeekToRec( rStCtrl, PPT_PST_NotesAtom, aSlideHd.GetRecEndFilePos() ) )
1598 ReadPptNotesAtom( rStCtrl, rE2.aNotesAtom );
1599 aSlideHd.SeekToContent( rStCtrl );
1600
1601 DffRecordHeader aPPTDrawingHd;
1602 if ( SeekToRec( rStCtrl, PPT_PST_PPDrawing, aSlideHd.GetRecEndFilePos(), &aPPTDrawingHd ) )
1603 {
1604 DffRecordHeader aPPTDgContainer;
1605 if ( SeekToRec( rStCtrl, DFF_msofbtDgContainer, aPPTDrawingHd.GetRecEndFilePos(), &aPPTDgContainer ) )
1606 {
1607 if ( SeekToRec( rStCtrl, DFF_msofbtDg, aPPTDrawingHd.GetRecEndFilePos() ) )
1608 {
1609 DffRecordHeader aDgRecordHeader;
1610 ReadDffRecordHeader( rStCtrl, aDgRecordHeader );
1611 rE2.nDrawingDgId = aDgRecordHeader.nRecInstance;
1612 aDgRecordHeader.SeekToEndOfRecord( rStCtrl );
1613 }
1614 if ( SeekToRec( rStCtrl, DFF_msofbtSolverContainer, aPPTDgContainer.GetRecEndFilePos() ) )
1615 {
1616 rE2.xSolverContainer.reset(new SvxMSDffSolverContainer);
1617 ReadSvxMSDffSolverContainer(rStCtrl, *rE2.xSolverContainer);
1618 }
1619 aPPTDgContainer.SeekToBegOfRecord( rStCtrl );
1620 SetDgContainer( rStCtrl ); // set this, so that the escherimport is knowing of our drawings
1621 }
1622 }
1623 // office xp is supporting more than one stylesheet
1624 if ( ( rE2.ePageKind == PPT_MASTERPAGE ) && ( rE2.aSlideAtom.nMasterId == 0 ) && !rE2.bNotesMaster )
1625 {
1626 PPTTextSpecInfo aTxSI( 0 );
1627 if ( aTxSIStyle.bValid && !aTxSIStyle.aList.empty() )
1628 aTxSI = aTxSIStyle.aList[ 0 ];
1629
1630 rE2.xStyleSheet = std::make_unique<PPTStyleSheet>(aSlideHd, rStCtrl, *this, aTxPFStyle, aTxSI);
1631 m_pDefaultSheet = rE2.xStyleSheet.get();
1632 }
1633 if ( SeekToRec( rStCtrl, PPT_PST_ColorSchemeAtom, aSlideHd.GetRecEndFilePos() ) )
1634 ReadPptColorSchemeAtom( rStCtrl, rE2.aColorScheme );
1635 else
1636 {
1637 OSL_FAIL( "SdrPowerPointImport::Ctor(): could not get SlideColorScheme! (SJ)" );
1638 }
1639 }
1640 else
1641 {
1642 OSL_FAIL("SdrPowerPointImport::Ctor(): Persist entry is flawed! (SJ)");
1643 }
1644 }
1645 }
1646 }
1647 DffRecordHeader* pHeadersFootersHd = aDocRecManager.GetRecordHeader( PPT_PST_HeadersFooters );
1648 if ( pHeadersFootersHd )
1649 {
1650 HeaderFooterEntry aNormalMaster, aNotesMaster;
1651 for ( ; pHeadersFootersHd; pHeadersFootersHd = aDocRecManager.GetRecordHeader( PPT_PST_HeadersFooters, SEEK_FROM_CURRENT ) )
1652 {
1653 if ( pHeadersFootersHd->nRecInstance == 3 ) // normal master
1654 ImportHeaderFooterContainer( *pHeadersFootersHd, aNormalMaster );
1655 else if ( pHeadersFootersHd->nRecInstance == 4 ) // notes master
1656 ImportHeaderFooterContainer( *pHeadersFootersHd, aNotesMaster );
1657 }
1658 for (size_t i = 0; i < m_pMasterPages->size(); i++)
1659 {
1660 if ((*m_pMasterPages)[ i ].bNotesMaster)
1661 (*m_pMasterPages)[ i ].xHeaderFooterEntry.reset(new HeaderFooterEntry(aNotesMaster));
1662 else
1663 (*m_pMasterPages)[ i ].xHeaderFooterEntry.reset(new HeaderFooterEntry(aNormalMaster));
1664 }
1665 }
1666 }
1667 }
1668 if ( ( rStCtrl.GetError() != ERRCODE_NONE ) || ( m_pDefaultSheet == nullptr ) )
1669 m_bOk = false;
1670 m_pPPTStyleSheet = m_pDefaultSheet;
1671 rStCtrl.Seek( 0 );
1672 }
1673
~SdrPowerPointImport()1674 SdrPowerPointImport::~SdrPowerPointImport()
1675 {
1676 m_pMasterPages.reset();
1677 m_pSlidePages.reset();
1678 m_pNotePages.reset();
1679 }
1680
ReadOCXStream(tools::SvRef<SotStorage> & rSrc,css::uno::Reference<css::drawing::XShape> * pShapeRef)1681 bool PPTConvertOCXControls::ReadOCXStream( tools::SvRef<SotStorage>& rSrc,
1682 css::uno::Reference< css::drawing::XShape > *pShapeRef )
1683 {
1684 bool bRes = false;
1685 uno::Reference< form::XFormComponent > xFComp;
1686 if ( mpPPTImporter && mpPPTImporter->ReadFormControl( rSrc, xFComp ) )
1687 {
1688 if ( xFComp.is() )
1689 {
1690 css::awt::Size aSz; // not used in import
1691 bRes = InsertControl( xFComp, aSz,pShapeRef, false/*bFloatingCtrl*/);
1692 }
1693 }
1694 return bRes;
1695 }
1696
InsertControl(const css::uno::Reference<css::form::XFormComponent> & rFComp,const css::awt::Size & rSize,css::uno::Reference<css::drawing::XShape> * pShape,bool)1697 bool PPTConvertOCXControls::InsertControl(
1698 const css::uno::Reference< css::form::XFormComponent > &rFComp,
1699 const css::awt::Size& rSize,
1700 css::uno::Reference< css::drawing::XShape > *pShape,
1701 bool /*bFloatingCtrl*/)
1702 {
1703 bool bRetValue = false;
1704 try
1705 {
1706 css::uno::Reference< css::drawing::XShape > xShape;
1707
1708 const css::uno::Reference< css::container::XIndexContainer > & rFormComps =
1709 GetFormComps();
1710
1711 css::uno::Any aTmp( &rFComp, cppu::UnoType<css::form::XFormComponent>::get() );
1712
1713 rFormComps->insertByIndex( rFormComps->getCount(), aTmp );
1714
1715 const css::uno::Reference< css::lang::XMultiServiceFactory > & rServiceFactory =
1716 GetServiceFactory();
1717 if( rServiceFactory.is() )
1718 {
1719 css::uno::Reference< css::uno::XInterface > xCreate = rServiceFactory
1720 ->createInstance( "com.sun.star.drawing.ControlShape" );
1721 if( xCreate.is() )
1722 {
1723 xShape.set(xCreate, css::uno::UNO_QUERY);
1724 if ( xShape.is() )
1725 {
1726 xShape->setSize(rSize);
1727 // set the Control-Model at the Control-Shape
1728 css::uno::Reference< css::drawing::XControlShape > xControlShape( xShape,
1729 css::uno::UNO_QUERY );
1730 css::uno::Reference< css::awt::XControlModel > xControlModel( rFComp,
1731 css::uno::UNO_QUERY );
1732 if ( xControlShape.is() && xControlModel.is() )
1733 {
1734 xControlShape->setControl( xControlModel );
1735 if (pShape)
1736 *pShape = xShape;
1737 bRetValue = true;
1738 }
1739 }
1740 }
1741 }
1742 }
1743 catch( ... )
1744 {
1745 bRetValue = false;
1746 }
1747 return bRetValue;
1748 };
GetDrawPage()1749 void PPTConvertOCXControls::GetDrawPage()
1750 {
1751 if( xDrawPage.is() || !mxModel.is() )
1752 return;
1753
1754 css::uno::Reference< css::drawing::XDrawPages > xDrawPages;
1755 switch( ePageKind )
1756 {
1757 case PPT_SLIDEPAGE :
1758 case PPT_NOTEPAGE :
1759 {
1760 css::uno::Reference< css::drawing::XDrawPagesSupplier >
1761 xDrawPagesSupplier( mxModel, css::uno::UNO_QUERY);
1762 if ( xDrawPagesSupplier.is() )
1763 xDrawPages = xDrawPagesSupplier->getDrawPages();
1764 }
1765 break;
1766
1767 case PPT_MASTERPAGE :
1768 {
1769 css::uno::Reference< css::drawing::XMasterPagesSupplier >
1770 xMasterPagesSupplier( mxModel, css::uno::UNO_QUERY);
1771 if ( xMasterPagesSupplier.is() )
1772 xDrawPages = xMasterPagesSupplier->getMasterPages();
1773 }
1774 break;
1775 }
1776 if ( xDrawPages.is() && xDrawPages->getCount() )
1777 {
1778 xDrawPages->getCount();
1779 css::uno::Any aAny( xDrawPages->getByIndex( xDrawPages->getCount() - 1 ) );
1780 aAny >>= xDrawPage;
1781 }
1782 }
1783
SdrPowerPointOLEDecompress(SvStream & rOutput,SvStream & rInput,sal_uInt32 nInputSize)1784 static bool SdrPowerPointOLEDecompress( SvStream& rOutput, SvStream& rInput, sal_uInt32 nInputSize )
1785 {
1786 sal_uInt32 nOldPos = rInput.Tell();
1787 std::unique_ptr<char[]> pBuf(new char[ nInputSize ]);
1788 rInput.ReadBytes(pBuf.get(), nInputSize);
1789 ZCodec aZCodec( 0x8000, 0x8000 );
1790 aZCodec.BeginCompression();
1791 SvMemoryStream aSource( pBuf.get(), nInputSize, StreamMode::READ );
1792 aZCodec.Decompress( aSource, rOutput );
1793 const bool bSuccess(0 != aZCodec.EndCompression());
1794 rInput.Seek( nOldPos );
1795 return bSuccess;
1796 }
1797
1798 // #i32596# - add new parameter <_nCalledByGroup>
ImportOLE(sal_uInt32 nOLEId,const Graphic & rGraf,const tools::Rectangle & rBoundRect,const tools::Rectangle & rVisArea,const int) const1799 SdrObject* SdrPowerPointImport::ImportOLE( sal_uInt32 nOLEId,
1800 const Graphic& rGraf,
1801 const tools::Rectangle& rBoundRect,
1802 const tools::Rectangle& rVisArea,
1803 const int /*_nCalledByGroup*/ ) const
1804 {
1805 SdrObject* pRet = nullptr;
1806
1807 sal_uInt32 nOldPos = rStCtrl.Tell();
1808
1809 Graphic aGraphic( rGraf );
1810
1811 if ( const_cast<SdrPowerPointImport*>(this)->maShapeRecords.SeekToContent( rStCtrl, DFF_msofbtClientData, SEEK_FROM_CURRENT_AND_RESTART ) )
1812 {
1813 DffRecordHeader aPlaceHd;
1814
1815 auto nEndRecPos = SanitizeEndPos(rStCtrl, const_cast<SdrPowerPointImport*>(this)->maShapeRecords.Current()->GetRecEndFilePos());
1816 while ( ( rStCtrl.GetError() == ERRCODE_NONE )
1817 && ( rStCtrl.Tell() < nEndRecPos ) )
1818 {
1819 ReadDffRecordHeader( rStCtrl, aPlaceHd );
1820 if ( aPlaceHd.nRecType == PPT_PST_RecolorInfoAtom )
1821 {
1822 const_cast<SdrPowerPointImport*>(this)->RecolorGraphic( rStCtrl, aPlaceHd.nRecLen, aGraphic );
1823 break;
1824 }
1825 else
1826 {
1827 if (!aPlaceHd.SeekToEndOfRecord(rStCtrl))
1828 break;
1829 }
1830 }
1831 }
1832
1833 for (PPTOleEntry& rOe : const_cast<SdrPowerPointImport*>(this)->aOleObjectList)
1834 {
1835 if ( rOe.nId != nOLEId )
1836 continue;
1837
1838 rStCtrl.Seek( rOe.nRecHdOfs );
1839
1840 DffRecordHeader aHd;
1841 ReadDffRecordHeader( rStCtrl, aHd );
1842
1843 sal_uInt32 nLen = aHd.nRecLen - 4;
1844 if ( static_cast<sal_Int32>(nLen) > 0 )
1845 {
1846 bool bSuccess = false;
1847
1848 rStCtrl.SeekRel( 4 );
1849
1850 ::utl::TempFile aTmpFile;
1851 aTmpFile.EnableKillingFile();
1852
1853 if ( aTmpFile.IsValid() )
1854 {
1855 SvStream* pDest = aTmpFile.GetStream(StreamMode::TRUNC | StreamMode::WRITE);
1856 if (pDest)
1857 {
1858 bSuccess = SdrPowerPointOLEDecompress( *pDest, rStCtrl, nLen );
1859 }
1860 aTmpFile.CloseStream();
1861 }
1862 if ( bSuccess )
1863 {
1864 SvStream* pDest = aTmpFile.GetStream(StreamMode::READ);
1865 Storage* pObjStor = pDest ? new Storage( *pDest, true ) : nullptr;
1866 if (pObjStor)
1867 {
1868 tools::SvRef<SotStorage> xObjStor( new SotStorage( pObjStor ) );
1869 if ( xObjStor.is() && !xObjStor->GetError() )
1870 {
1871 if ( xObjStor->GetClassName() == SvGlobalName() )
1872 {
1873 xObjStor->SetClass( SvGlobalName( pObjStor->GetClassId() ), pObjStor->GetFormat(), pObjStor->GetUserName() );
1874 }
1875 tools::SvRef<SotStorageStream> xSrcTst = xObjStor->OpenSotStream( "\1Ole" );
1876 if ( xSrcTst.is() )
1877 {
1878 sal_uInt8 aTestA[ 10 ];
1879 bool bGetItAsOle = (sizeof(aTestA) == xSrcTst->ReadBytes(aTestA, sizeof(aTestA)));
1880 if ( !bGetItAsOle )
1881 { // maybe there is a contents stream in here
1882 xSrcTst = xObjStor->OpenSotStream( "Contents", StreamMode::READWRITE | StreamMode::NOCREATE );
1883 bGetItAsOle = (xSrcTst.is() &&
1884 sizeof(aTestA) == xSrcTst->ReadBytes(aTestA, sizeof(aTestA)));
1885 }
1886 if ( bGetItAsOle )
1887 {
1888 OUString aNm;
1889 // if ( nSvxMSDffOLEConvFlags )
1890 {
1891 uno::Reference < embed::XStorage > xDestStorage( rOe.pShell->GetStorage() );
1892 uno::Reference < embed::XEmbeddedObject > xObj =
1893 CheckForConvertToSOObj(nSvxMSDffOLEConvFlags, *xObjStor, xDestStorage, rGraf, rVisArea, maBaseURL);
1894 if( xObj.is() )
1895 {
1896 rOe.pShell->getEmbeddedObjectContainer().InsertEmbeddedObject( xObj, aNm );
1897
1898 svt::EmbeddedObjectRef aObj( xObj, rOe.nAspect );
1899
1900 // TODO/LATER: need MediaType for Graphic
1901 aObj.SetGraphic( rGraf, OUString() );
1902 pRet = new SdrOle2Obj(
1903 *pSdrModel,
1904 aObj,
1905 aNm,
1906 rBoundRect);
1907 }
1908 }
1909 if ( !pRet && ( rOe.nType == PPT_PST_ExControl ) )
1910 {
1911 uno::Reference< frame::XModel > xModel( rOe.pShell->GetModel() );
1912 PPTConvertOCXControls aPPTConvertOCXControls( this, xModel, m_eCurrentPageKind );
1913 css::uno::Reference< css::drawing::XShape > xShape;
1914 if ( aPPTConvertOCXControls.ReadOCXStream( xObjStor, &xShape ) )
1915 pRet = GetSdrObjectFromXShape( xShape );
1916
1917 }
1918 if ( !pRet )
1919 {
1920 aNm = rOe.pShell->getEmbeddedObjectContainer().CreateUniqueObjectName();
1921
1922 // object is not an own object
1923 const css::uno::Reference < css::embed::XStorage >& rStorage = rOe.pShell->GetStorage();
1924 if (rStorage.is())
1925 {
1926 tools::SvRef<SotStorage> xTarget = SotStorage::OpenOLEStorage(rStorage, aNm, StreamMode::READWRITE);
1927 if (xObjStor.is() && xTarget.is())
1928 {
1929 xObjStor->CopyTo(xTarget.get());
1930 if (!xTarget->GetError())
1931 xTarget->Commit();
1932 }
1933 xTarget.clear();
1934 }
1935
1936 uno::Reference < embed::XEmbeddedObject > xObj =
1937 rOe.pShell->getEmbeddedObjectContainer().GetEmbeddedObject( aNm );
1938 if ( xObj.is() )
1939 {
1940 if ( rOe.nAspect != embed::Aspects::MSOLE_ICON )
1941 {
1942 //TODO/LATER: keep on hacking?!
1943 // we don't want to be modified
1944 //xInplaceObj->EnableSetModified( sal_False );
1945 if ( rVisArea.IsEmpty() )
1946 {
1947 MapUnit aMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( rOe.nAspect ) );
1948 Size aSize( OutputDevice::LogicToLogic( aGraphic.GetPrefSize(),
1949 aGraphic.GetPrefMapMode(), MapMode( aMapUnit ) ) );
1950
1951 awt::Size aSz;
1952 aSz.Width = aSize.Width();
1953 aSz.Height = aSize.Height();
1954 xObj->setVisualAreaSize( rOe.nAspect, aSz );
1955 }
1956 else
1957 {
1958 awt::Size aSize( rVisArea.GetSize().Width(), rVisArea.GetSize().Height() );
1959 xObj->setVisualAreaSize( rOe.nAspect, aSize );
1960 }
1961 //xInplaceObj->EnableSetModified( sal_True );
1962 }
1963
1964 svt::EmbeddedObjectRef aObj( xObj, rOe.nAspect );
1965
1966 // TODO/LATER: need MediaType for Graphic
1967 aObj.SetGraphic( aGraphic, OUString() );
1968
1969 pRet = new SdrOle2Obj(
1970 *pSdrModel,
1971 aObj,
1972 aNm,
1973 rBoundRect);
1974 }
1975 }
1976 }
1977 }
1978 }
1979 }
1980 aTmpFile.CloseStream();
1981 }
1982 }
1983 }
1984 rStCtrl.Seek( nOldPos );
1985
1986 return pRet;
1987 }
1988
ImportExOleObjStg(sal_uInt32 nPersistPtr,sal_uInt32 & nOleId) const1989 std::unique_ptr<SvMemoryStream> SdrPowerPointImport::ImportExOleObjStg( sal_uInt32 nPersistPtr, sal_uInt32& nOleId ) const
1990 {
1991 std::unique_ptr<SvMemoryStream> pRet;
1992 if ( nPersistPtr && ( nPersistPtr < m_nPersistPtrCnt ) )
1993 {
1994 sal_uInt32 nOldPos, nOfs = m_pPersistPtr[ nPersistPtr ];
1995 nOldPos = rStCtrl.Tell();
1996 rStCtrl.Seek( nOfs );
1997 DffRecordHeader aHd;
1998 ReadDffRecordHeader( rStCtrl, aHd );
1999 if ( aHd.nRecType == DFF_PST_ExOleObjStg )
2000 {
2001 sal_uInt32 nLen = aHd.nRecLen - 4;
2002 if ( static_cast<sal_Int32>(nLen) > 0 )
2003 {
2004 rStCtrl.ReadUInt32( nOleId );
2005 pRet.reset(new SvMemoryStream);
2006 ZCodec aZCodec( 0x8000, 0x8000 );
2007 aZCodec.BeginCompression();
2008 aZCodec.Decompress( rStCtrl, *pRet );
2009 if ( !aZCodec.EndCompression() )
2010 {
2011 pRet.reset();
2012 }
2013 }
2014 }
2015 rStCtrl.Seek( nOldPos );
2016 }
2017 return pRet;
2018 }
2019
SeekOle(SfxObjectShell * pShell,sal_uInt32 nFilterOptions)2020 void SdrPowerPointImport::SeekOle( SfxObjectShell* pShell, sal_uInt32 nFilterOptions )
2021 {
2022 if ( !pShell )
2023 return;
2024
2025 DffRecordHeader* pHd;
2026
2027 sal_uInt32 nOldPos = rStCtrl.Tell();
2028 if ( nFilterOptions & 1 )
2029 {
2030 pHd = aDocRecManager.GetRecordHeader( PPT_PST_List );
2031 if ( pHd )
2032 {
2033 // we try to locate the basic atom
2034 pHd->SeekToContent( rStCtrl );
2035 if ( SeekToRec( rStCtrl, PPT_PST_VBAInfo, pHd->GetRecEndFilePos(), pHd ) )
2036 {
2037 if ( SeekToRec( rStCtrl, PPT_PST_VBAInfoAtom, pHd->GetRecEndFilePos(), pHd ) )
2038 {
2039 sal_uInt32 nPersistPtr, nIDoNotKnow1, nIDoNotKnow2;
2040 rStCtrl.ReadUInt32( nPersistPtr )
2041 .ReadUInt32( nIDoNotKnow1 )
2042 .ReadUInt32( nIDoNotKnow2 );
2043
2044 sal_uInt32 nOleId;
2045 std::unique_ptr<SvMemoryStream> pBas = ImportExOleObjStg( nPersistPtr, nOleId );
2046 if ( pBas )
2047 {
2048 tools::SvRef<SotStorage> xSource( new SotStorage( pBas.release(), true ) );
2049 tools::SvRef<SotStorage> xDest( new SotStorage( new SvMemoryStream(), true ) );
2050 if ( xSource.is() && xDest.is() )
2051 {
2052 // is this a visual basic storage ?
2053 tools::SvRef<SotStorage> xSubStorage = xSource->OpenSotStorage( "VBA",
2054 StreamMode::READWRITE | StreamMode::NOCREATE | StreamMode::SHARE_DENYALL );
2055 if( xSubStorage.is() && ( ERRCODE_NONE == xSubStorage->GetError() ) )
2056 {
2057 tools::SvRef<SotStorage> xMacros = xDest->OpenSotStorage( "MACROS" );
2058 if ( xMacros.is() )
2059 {
2060 SvStorageInfoList aList;
2061 xSource->FillInfoList( &aList );
2062 SvStorageInfoList::size_type i;
2063
2064 bool bCopied = true;
2065 for ( i = 0; i < aList.size(); i++ ) // copy all entries
2066 {
2067 const SvStorageInfo& rInfo = aList[ i ];
2068 if ( !xSource->CopyTo( rInfo.GetName(), xMacros.get(), rInfo.GetName() ) )
2069 bCopied = false;
2070 }
2071 if ( i && bCopied )
2072 {
2073 uno::Reference < embed::XStorage > xDoc( pShell->GetStorage() );
2074 if ( xDoc.is() )
2075 {
2076 tools::SvRef<SotStorage> xVBA = SotStorage::OpenOLEStorage( xDoc, SvxImportMSVBasic::GetMSBasicStorageName() );
2077 if ( xVBA.is() && ( xVBA->GetError() == ERRCODE_NONE ) )
2078 {
2079 tools::SvRef<SotStorage> xSubVBA = xVBA->OpenSotStorage( "_MS_VBA_Overhead" );
2080 if ( xSubVBA.is() && ( xSubVBA->GetError() == ERRCODE_NONE ) )
2081 {
2082 tools::SvRef<SotStorageStream> xOriginal = xSubVBA->OpenSotStream( "_MS_VBA_Overhead2" );
2083 if ( xOriginal.is() && ( xOriginal->GetError() == ERRCODE_NONE ) )
2084 {
2085 if ( nPersistPtr && ( nPersistPtr < m_nPersistPtrCnt ) )
2086 {
2087 rStCtrl.Seek( m_pPersistPtr[ nPersistPtr ] );
2088 ReadDffRecordHeader( rStCtrl, *pHd );
2089
2090 xOriginal->WriteUInt32( nIDoNotKnow1 )
2091 .WriteUInt32( nIDoNotKnow2 );
2092
2093 sal_uInt32 nToCopy, nBufSize;
2094 nToCopy = pHd->nRecLen;
2095 std::unique_ptr<sal_uInt8[]> pBuf(new sal_uInt8[ 0x40000 ]); // 256KB Buffer
2096 while ( nToCopy )
2097 {
2098 nBufSize = ( nToCopy >= 0x40000 ) ? 0x40000 : nToCopy;
2099 rStCtrl.ReadBytes(pBuf.get(), nBufSize);
2100 xOriginal->WriteBytes(pBuf.get(), nBufSize);
2101 nToCopy -= nBufSize;
2102 }
2103 }
2104 }
2105 }
2106 }
2107 xVBA->Commit();
2108 }
2109 }
2110 }
2111 }
2112 }
2113 }
2114 }
2115 }
2116 }
2117 }
2118 pHd = aDocRecManager.GetRecordHeader( PPT_PST_ExObjList );
2119 if ( pHd )
2120 {
2121 DffRecordHeader* pExEmbed = nullptr;
2122
2123 pHd->SeekToBegOfRecord( rStCtrl );
2124 DffRecordManager aExObjListManager( rStCtrl );
2125 sal_uInt16 i, nRecType(PPT_PST_ExEmbed);
2126
2127 for ( i = 0; i < 2; i++ )
2128 {
2129 switch ( i )
2130 {
2131 case 0 : nRecType = PPT_PST_ExEmbed; break;
2132 case 1 : nRecType = PPT_PST_ExControl; break;
2133 }
2134 for ( pExEmbed = aExObjListManager.GetRecordHeader( nRecType );
2135 pExEmbed; pExEmbed = aExObjListManager.GetRecordHeader( nRecType, SEEK_FROM_CURRENT ) )
2136 {
2137 pExEmbed->SeekToContent( rStCtrl );
2138
2139 DffRecordHeader aExOleAtHd;
2140 if ( SeekToRec( rStCtrl, PPT_PST_ExOleObjAtom, pExEmbed->GetRecEndFilePos(), &aExOleAtHd ) )
2141 {
2142 PptExOleObjAtom aAt;
2143 ReadPptExOleObjAtom( rStCtrl, aAt );
2144
2145 if ( aAt.nPersistPtr && ( aAt.nPersistPtr < m_nPersistPtrCnt ) )
2146 {
2147 rStCtrl.Seek( m_pPersistPtr[ aAt.nPersistPtr ] );
2148 DffRecordHeader aHd;
2149 ReadDffRecordHeader( rStCtrl, aHd );
2150 if ( aHd.nRecType == DFF_PST_ExOleObjStg )
2151 {
2152 sal_uInt32 nId;
2153 rStCtrl.ReadUInt32( nId );
2154 aOleObjectList.emplace_back(
2155 aAt.nId, aHd.nFilePos, pShell, nRecType, aAt.nAspect );
2156 }
2157 }
2158 }
2159 }
2160 }
2161 }
2162 rStCtrl.Seek( nOldPos );
2163 }
2164
ReadFontCollection()2165 bool SdrPowerPointImport::ReadFontCollection()
2166 {
2167 bool bRet = false;
2168 DffRecordHeader* pEnvHd = aDocRecManager.GetRecordHeader( PPT_PST_Environment );
2169 if ( pEnvHd )
2170 {
2171 sal_uLong nOldFPos = rStCtrl.Tell(); // remember FilePos for restoring it later
2172 pEnvHd->SeekToContent( rStCtrl );
2173 DffRecordHeader aListHd;
2174 if ( SeekToRec( rStCtrl, PPT_PST_FontCollection, pEnvHd->GetRecEndFilePos(), &aListHd ) )
2175 {
2176 sal_uInt16 nCount2 = 0;
2177 while ( SeekToRec( rStCtrl, PPT_PST_FontEntityAtom, aListHd.GetRecEndFilePos() ) )
2178 {
2179 bRet = true;
2180 if (!m_pFonts)
2181 m_pFonts.reset( new std::vector<std::unique_ptr<PptFontEntityAtom>> );
2182 std::unique_ptr<PptFontEntityAtom> pFont(new PptFontEntityAtom);
2183 ReadPptFontEntityAtom( rStCtrl, *pFont );
2184
2185 vcl::Font aFont;
2186 aFont.SetCharSet( pFont->eCharSet );
2187 aFont.SetFamilyName( pFont->aName );
2188 aFont.SetFamily( pFont->eFamily );
2189 aFont.SetPitch( pFont->ePitch );
2190 aFont.SetFontHeight( 100 );
2191
2192 // following block is necessary, because our old PowerPoint export did not set the
2193 // correct charset
2194 if ( pFont->aName.equalsIgnoreAsciiCase( "Wingdings" ) ||
2195 pFont->aName.equalsIgnoreAsciiCase( "Wingdings 2" ) ||
2196 pFont->aName.equalsIgnoreAsciiCase( "Wingdings 3" ) ||
2197 pFont->aName.equalsIgnoreAsciiCase( "Monotype Sorts" ) ||
2198 pFont->aName.equalsIgnoreAsciiCase( "Monotype Sorts 2" ) ||
2199 pFont->aName.equalsIgnoreAsciiCase( "Webdings" ) ||
2200 pFont->aName.equalsIgnoreAsciiCase( "StarBats" ) ||
2201 pFont->aName.equalsIgnoreAsciiCase( "StarMath" ) ||
2202 pFont->aName.equalsIgnoreAsciiCase( "ZapfDingbats" ) )
2203 {
2204 pFont->eCharSet = RTL_TEXTENCODING_SYMBOL;
2205 };
2206 m_pFonts->insert(m_pFonts->begin() + nCount2++, std::move(pFont));
2207 }
2208 }
2209 rStCtrl.Seek( nOldFPos ); // restore FilePos
2210 }
2211 return bRet;
2212 }
2213
GetPageList(PptPageKind ePageKind) const2214 PptSlidePersistList* SdrPowerPointImport::GetPageList(PptPageKind ePageKind) const
2215 {
2216 switch (ePageKind)
2217 {
2218 case PPT_MASTERPAGE:
2219 return m_pMasterPages.get();
2220 case PPT_SLIDEPAGE:
2221 return m_pSlidePages.get();
2222 case PPT_NOTEPAGE:
2223 return m_pNotePages.get();
2224 }
2225 return nullptr;
2226 }
2227
GetDrawOutliner(SdrTextObj const * pSdrText)2228 SdrOutliner* SdrPowerPointImport::GetDrawOutliner( SdrTextObj const * pSdrText )
2229 {
2230 if ( !pSdrText )
2231 return nullptr;
2232 else
2233 return &pSdrText->ImpGetDrawOutliner();
2234 }
2235
2236
ReadObjText(PPTTextObj * pTextObj,SdrObject * pSdrObj,SdPageCapsule pPage) const2237 SdrObject* SdrPowerPointImport::ReadObjText( PPTTextObj* pTextObj, SdrObject* pSdrObj, SdPageCapsule pPage ) const
2238 {
2239 SdrTextObj* pText = dynamic_cast<SdrTextObj*>( pSdrObj );
2240 if ( pText )
2241 {
2242 if ( !ApplyTextObj( pTextObj, pText, pPage, nullptr, nullptr ) )
2243 pSdrObj = nullptr;
2244 }
2245 return pSdrObj;
2246 }
2247
ApplyTextObj(PPTTextObj * pTextObj,SdrTextObj * pSdrText,SdPageCapsule,SfxStyleSheet * pSheet,SfxStyleSheet ** ppStyleSheetAry) const2248 SdrObject* SdrPowerPointImport::ApplyTextObj( PPTTextObj* pTextObj, SdrTextObj* pSdrText, SdPageCapsule /*pPage*/,
2249 SfxStyleSheet* pSheet, SfxStyleSheet** ppStyleSheetAry ) const
2250 {
2251 SdrTextObj* pText = pSdrText;
2252 if ( pTextObj->Count() )
2253 {
2254 TSS_Type nDestinationInstance = pTextObj->GetDestinationInstance() ;
2255 SdrOutliner& rOutliner = pText->ImpGetDrawOutliner();
2256 bool bUndoEnabled = rOutliner.IsUndoEnabled();
2257 rOutliner.EnableUndo(false);
2258
2259 if ( ( pText->GetObjInventor() == SdrInventor::Default ) && ( pText->GetObjIdentifier() == OBJ_TITLETEXT ) ) // Outliner-Style for Title-Text object?!? (->of DL)
2260 rOutliner.Init( OutlinerMode::TitleObject ); // Outliner reset
2261
2262 bool bOldUpdateMode = rOutliner.GetUpdateMode();
2263 rOutliner.SetUpdateMode( false );
2264 if ( pSheet )
2265 {
2266 if ( rOutliner.GetStyleSheet( 0 ) != pSheet )
2267 rOutliner.SetStyleSheet( 0, pSheet );
2268 }
2269 rOutliner.SetVertical( pTextObj->GetVertical() );
2270 for ( PPTParagraphObj* pPara = pTextObj->First(); pPara; pPara = pTextObj->Next() )
2271 {
2272 sal_uInt32 nTextSize = pPara->GetTextSize();
2273 if ( ! ( nTextSize & 0xffff0000 ) )
2274 {
2275 PPTPortionObj* pPortion;
2276 std::unique_ptr<sal_Unicode[]> pParaText(new sal_Unicode[ nTextSize ]);
2277 sal_Int32 nCurrentIndex = 0;
2278 for ( pPortion = pPara->First(); pPortion; pPortion = pPara->Next() )
2279 {
2280 if ( pPortion->mpFieldItem )
2281 pParaText[ nCurrentIndex++ ] = ' ';
2282 else
2283 {
2284 sal_Int32 nCharacters = pPortion->Count();
2285 const sal_Unicode* pSource = pPortion->maString.getStr();
2286 sal_Unicode* pDest = pParaText.get() + nCurrentIndex;
2287
2288 sal_uInt32 nFont;
2289 pPortion->GetAttrib( PPT_CharAttr_Font, nFont, pTextObj->GetInstance() );
2290 PptFontEntityAtom* pFontEnityAtom = GetFontEnityAtom( nFont );
2291 if ( pFontEnityAtom && ( pFontEnityAtom->eCharSet == RTL_TEXTENCODING_SYMBOL ) )
2292 {
2293 sal_Unicode nUnicode;
2294 for (sal_Int32 i = 0; i < nCharacters; i++ )
2295 {
2296 nUnicode = pSource[ i ];
2297 if ( ! ( nUnicode & 0xff00 ) )
2298 nUnicode |= 0xf000;
2299 pDest[ i ] = nUnicode;
2300 }
2301 }
2302 else
2303 memcpy( pDest, pSource, nCharacters << 1 );
2304 nCurrentIndex += nCharacters;
2305 }
2306 }
2307 sal_Int32 nParaIndex = pTextObj->GetCurrentIndex();
2308 SfxStyleSheet* pS = ppStyleSheetAry ? ppStyleSheetAry[ pPara->mxParaSet->mnDepth ] : pSheet;
2309
2310 ESelection aSelection( nParaIndex, 0, nParaIndex, 0 );
2311 rOutliner.Insert( OUString(), nParaIndex, pPara->mxParaSet->mnDepth );
2312 rOutliner.QuickInsertText( OUString(pParaText.get(), nCurrentIndex), aSelection );
2313 rOutliner.SetParaAttribs( nParaIndex, rOutliner.GetEmptyItemSet() );
2314 if ( pS )
2315 rOutliner.SetStyleSheet( nParaIndex, pS );
2316
2317 for ( pPortion = pPara->First(); pPortion; pPortion = pPara->Next() )
2318 {
2319 SfxItemSet aPortionAttribs( rOutliner.GetEmptyItemSet() );
2320 std::unique_ptr<SvxFieldItem> pFieldItem(pPortion->GetTextField());
2321 if ( pFieldItem )
2322 {
2323 rOutliner.QuickInsertField( *pFieldItem, ESelection( nParaIndex, aSelection.nEndPos, nParaIndex, aSelection.nEndPos + 1 ) );
2324 aSelection.nEndPos++;
2325 }
2326 else
2327 {
2328 const sal_Unicode *pF, *pPtr = pPortion->maString.getStr();
2329 const sal_Unicode *pMax = pPtr + pPortion->maString.getLength();
2330 sal_Int32 nLen;
2331 for ( pF = pPtr; pPtr < pMax; pPtr++ )
2332 {
2333 if ( *pPtr == 0xb )
2334 {
2335 nLen = pPtr - pF;
2336 if ( nLen )
2337 aSelection.nEndPos =
2338 sal::static_int_cast< sal_uInt16 >(
2339 aSelection.nEndPos + nLen );
2340 pF = pPtr + 1;
2341 rOutliner.QuickInsertLineBreak( ESelection( nParaIndex, aSelection.nEndPos, nParaIndex, aSelection.nEndPos + 1 ) );
2342 aSelection.nEndPos++;
2343 }
2344 }
2345 nLen = pPtr - pF;
2346 if ( nLen )
2347 aSelection.nEndPos = sal::static_int_cast< sal_uInt16 >(
2348 aSelection.nEndPos + nLen );
2349 }
2350 pPortion->ApplyTo( aPortionAttribs, const_cast<SdrPowerPointImport&>(*this), nDestinationInstance, pTextObj );
2351 rOutliner.QuickSetAttribs( aPortionAttribs, aSelection );
2352 aSelection.nStartPos = aSelection.nEndPos;
2353 }
2354 std::optional< sal_Int16 > oStartNumbering;
2355 SfxItemSet aParagraphAttribs( rOutliner.GetEmptyItemSet() );
2356 pPara->ApplyTo( aParagraphAttribs, oStartNumbering, *this, nDestinationInstance );
2357
2358 sal_uInt32 nIsBullet2 = 0; //, nInstance = nDestinationInstance != 0xffffffff ? nDestinationInstance : pTextObj->GetInstance();
2359 pPara->GetAttrib( PPT_ParaAttr_BulletOn, nIsBullet2, nDestinationInstance );
2360 if ( !nIsBullet2 )
2361 aParagraphAttribs.Put( SfxBoolItem( EE_PARA_BULLETSTATE, false ) );
2362
2363 if ( !aSelection.nStartPos ) // in PPT empty paragraphs never gets a bullet
2364 {
2365 aParagraphAttribs.Put( SfxBoolItem( EE_PARA_BULLETSTATE, false ) );
2366 }
2367 aSelection.nStartPos = 0;
2368 rOutliner.QuickSetAttribs( aParagraphAttribs, aSelection );
2369 }
2370 }
2371 std::unique_ptr<OutlinerParaObject> pNewText = rOutliner.CreateParaObject();
2372 rOutliner.Clear();
2373 rOutliner.SetUpdateMode( bOldUpdateMode );
2374 rOutliner.EnableUndo(bUndoEnabled);
2375 pText->SetOutlinerParaObject( std::move(pNewText) );
2376 }
2377 return pText;
2378 }
2379
SeekToDocument(DffRecordHeader * pRecHd) const2380 bool SdrPowerPointImport::SeekToDocument( DffRecordHeader* pRecHd ) const
2381 {
2382 bool bRet;
2383 sal_uLong nOldFPos = rStCtrl.Tell(); // remember FilePos for restoring it should the situation arise
2384 rStCtrl.Seek( m_nDocStreamPos );
2385 DffRecordHeader aDocHd;
2386 ReadDffRecordHeader( rStCtrl, aDocHd );
2387 bRet = aDocHd.nRecType == PPT_PST_Document;
2388 if ( bRet )
2389 {
2390 if ( pRecHd )
2391 *pRecHd = aDocHd;
2392 else
2393 aDocHd.SeekToBegOfRecord( rStCtrl );
2394 }
2395 if ( !bRet )
2396 rStCtrl.Seek( nOldFPos ); // restore FilePos
2397 return bRet;
2398 }
2399
SeekToContentOfProgTag(sal_Int32 nVersion,SvStream & rSt,const DffRecordHeader & rSourceHd,DffRecordHeader & rContentHd)2400 bool SdrPowerPointImport::SeekToContentOfProgTag( sal_Int32 nVersion, SvStream& rSt,
2401 const DffRecordHeader& rSourceHd, DffRecordHeader& rContentHd )
2402 {
2403 bool bRetValue = false;
2404 sal_uInt32 nOldPos = rSt.Tell();
2405
2406 DffRecordHeader aProgTagsHd, aProgTagBinaryDataHd;
2407 rSourceHd.SeekToContent( rSt );
2408 bool bFound = rSourceHd.nRecType == PPT_PST_ProgTags;
2409 if ( !bFound )
2410 bFound = SeekToRec( rSt, PPT_PST_ProgTags, rSourceHd.GetRecEndFilePos(), &aProgTagsHd );
2411 if ( bFound )
2412 {
2413 while( SeekToRec( rSt, PPT_PST_ProgBinaryTag, aProgTagsHd.GetRecEndFilePos(), &aProgTagBinaryDataHd ) )
2414 {
2415 ReadDffRecordHeader( rSt, rContentHd );
2416 if ( rContentHd.nRecType == PPT_PST_CString )
2417 {
2418 sal_uInt16 n = 6;
2419 sal_uInt32 i = rContentHd.nRecLen >> 1;
2420 if ( i > n )
2421 {
2422 OUString aPre = read_uInt16s_ToOUString(rSt, n);
2423 n = static_cast<sal_uInt16>( i - 6 );
2424 OUString aSuf = read_uInt16s_ToOUString(rSt, n);
2425 sal_Int32 nV = aSuf.toInt32();
2426 if ( ( nV == nVersion ) && ( aPre == "___PPT" ) )
2427 {
2428 if (!rContentHd.SeekToEndOfRecord(rSt))
2429 {
2430 break;
2431 }
2432 ReadDffRecordHeader( rSt, rContentHd );
2433 if ( rContentHd.nRecType == PPT_PST_BinaryTagData )
2434 {
2435 bRetValue = true;
2436 break;
2437 }
2438 }
2439 }
2440 }
2441 if (!aProgTagBinaryDataHd.SeekToEndOfRecord(rSt))
2442 break;
2443 }
2444 }
2445 if ( !bRetValue )
2446 rSt.Seek( nOldPos );
2447 return bRetValue;
2448 }
2449
GetCurrentPageId()2450 sal_uInt32 SdrPowerPointImport::GetCurrentPageId()
2451 {
2452 PptSlidePersistList* pList = GetPageList( m_eCurrentPageKind );
2453 if ( pList && m_nCurrentPageNum < pList->size() )
2454 return (*pList)[ m_nCurrentPageNum ].aPersistAtom.nSlideId;
2455 return 0;
2456 }
2457
SeekToCurrentPage(DffRecordHeader * pRecHd) const2458 bool SdrPowerPointImport::SeekToCurrentPage( DffRecordHeader* pRecHd ) const
2459 {
2460 bool bRet = false;
2461 PptSlidePersistList* pList = GetPageList( m_eCurrentPageKind );
2462 if ( pList && ( m_nCurrentPageNum < pList->size() ) )
2463 {
2464 sal_uLong nPersist = (*pList)[ m_nCurrentPageNum ].aPersistAtom.nPsrReference;
2465 if ( nPersist > 0 && nPersist < m_nPersistPtrCnt )
2466 {
2467 sal_uLong nFPos = m_pPersistPtr[ nPersist ];
2468 if ( nFPos < nStreamLen )
2469 {
2470 rStCtrl.Seek( nFPos );
2471 if ( pRecHd )
2472 ReadDffRecordHeader( rStCtrl, *pRecHd );
2473 bRet = true;
2474 }
2475 }
2476 }
2477 return bRet;
2478 }
2479
GetPageCount(PptPageKind ePageKind) const2480 sal_uInt16 SdrPowerPointImport::GetPageCount( PptPageKind ePageKind ) const
2481 {
2482 PptSlidePersistList* pList = GetPageList( ePageKind );
2483 if ( pList )
2484 return pList->size();
2485 return 0;
2486 }
2487
SetPageNum(sal_uInt16 nPageNum,PptPageKind eKind)2488 void SdrPowerPointImport::SetPageNum( sal_uInt16 nPageNum, PptPageKind eKind )
2489 {
2490 m_eCurrentPageKind = eKind;
2491 m_nCurrentPageNum = nPageNum;
2492
2493 m_pPPTStyleSheet = nullptr;
2494
2495 bool bHasMasterPage = true;
2496 sal_uInt16 nMasterIndex = 0;
2497
2498 if ( eKind == PPT_MASTERPAGE )
2499 nMasterIndex = nPageNum;
2500 else
2501 {
2502 if ( HasMasterPage( nPageNum, eKind ) )
2503 nMasterIndex = GetMasterPageIndex( nPageNum, eKind );
2504 else
2505 bHasMasterPage = false;
2506 }
2507 if ( bHasMasterPage )
2508 {
2509 PptSlidePersistList* pPageList = GetPageList( PPT_MASTERPAGE );
2510 if ( pPageList && nMasterIndex < pPageList->size() )
2511 {
2512 PptSlidePersistEntry* pMasterPersist = &(*pPageList)[ nMasterIndex ];
2513 if (!pMasterPersist->xStyleSheet && pMasterPersist->aSlideAtom.nMasterId)
2514 {
2515 nMasterIndex = m_pMasterPages->FindPage( pMasterPersist->aSlideAtom.nMasterId );
2516 if ( nMasterIndex != PPTSLIDEPERSIST_ENTRY_NOTFOUND )
2517 pMasterPersist = &(*pPageList)[ nMasterIndex ];
2518 }
2519 m_pPPTStyleSheet = pMasterPersist->xStyleSheet.get();
2520 }
2521 }
2522 if ( !m_pPPTStyleSheet )
2523 m_pPPTStyleSheet = m_pDefaultSheet;
2524 }
2525
GetPageSize() const2526 Size SdrPowerPointImport::GetPageSize() const
2527 {
2528 Size aRet( IsNoteOrHandout( m_nCurrentPageNum ) ? aDocAtom.GetNotesPageSize() : aDocAtom.GetSlidesPageSize() );
2529 Scale( aRet );
2530 // PPT works with units of 576 dpi in any case. To avoid inaccuracies
2531 // I do round the last decimal digit away.
2532 if ( nMapMul > 2 * nMapDiv )
2533 {
2534 MapUnit eMap = pSdrModel->GetScaleUnit();
2535 bool bInch = IsInch( eMap );
2536 tools::Long nInchMul = 1, nInchDiv = 1;
2537 if ( bInch )
2538 { // temporarily convert size (for rounding it) from inch to metric units
2539 Fraction aFact(GetMapFactor(eMap,MapUnit::Map100thMM).X());
2540 nInchMul = aFact.GetNumerator();
2541 nInchDiv = aFact.GetDenominator();
2542 aRet.setWidth( BigMulDiv( aRet.Width(), nInchMul, nInchDiv ) );
2543 aRet.setHeight( BigMulDiv( aRet.Height(), nInchMul, nInchDiv ) );
2544 }
2545 aRet.AdjustWidth(5 ); aRet.setWidth( aRet.Width() / 10 ); aRet.setWidth( aRet.Width() * 10 );
2546 aRet.AdjustHeight(5 ); aRet.setHeight( aRet.Height() / 10 ); aRet.setHeight( aRet.Height() * 10 );
2547 if ( bInch )
2548 {
2549 aRet.setWidth( BigMulDiv( aRet.Width(), nInchDiv, nInchMul ) );
2550 aRet.setHeight( BigMulDiv( aRet.Height(), nInchDiv, nInchMul ) );
2551 }
2552 }
2553 return aRet;
2554 }
2555
GetColorFromPalette(sal_uInt16 nNum,Color & rColor) const2556 bool SdrPowerPointImport::GetColorFromPalette( sal_uInt16 nNum, Color& rColor ) const
2557 {
2558 if ( m_nPageColorsNum != m_nCurrentPageNum || m_ePageColorsKind != m_eCurrentPageKind )
2559 {
2560 sal_uInt16 nSlideFlags = 0;
2561 PptSlidePersistList* pPageList = GetPageList( m_eCurrentPageKind );
2562 if ( pPageList && ( m_nCurrentPageNum < pPageList->size() ) )
2563 {
2564 assert( !pPageList->is_null( m_nCurrentPageNum ) );
2565 const PptSlidePersistEntry& rE = (*pPageList)[ m_nCurrentPageNum ];
2566 nSlideFlags = rE.aSlideAtom.nFlags;
2567 if ( ! ( nSlideFlags & 2 ) )
2568 const_cast<SdrPowerPointImport*>(this)->m_aPageColors = rE.aColorScheme;
2569 }
2570 if ( nSlideFlags & 2 ) // follow master colorscheme?
2571 {
2572 PptSlidePersistList* pPageList2 = GetPageList( PPT_MASTERPAGE );
2573 if ( pPageList2 )
2574 {
2575 PptSlidePersistEntry* pMasterPersist = nullptr;
2576 if ( m_eCurrentPageKind == PPT_MASTERPAGE )
2577 pMasterPersist = &(*pPageList2)[ m_nCurrentPageNum ];
2578 else
2579 {
2580 if ( HasMasterPage( m_nCurrentPageNum, m_eCurrentPageKind ) )
2581 {
2582 sal_uInt16 nMasterNum = GetMasterPageIndex( m_nCurrentPageNum, m_eCurrentPageKind );
2583 if ( nMasterNum < pPageList2->size() )
2584 pMasterPersist = &(*pPageList2)[ nMasterNum ];
2585 }
2586 }
2587 if ( pMasterPersist )
2588 {
2589 while( (pMasterPersist->aSlideAtom.nFlags & 2) // it is possible that a masterpage
2590 && pMasterPersist->aSlideAtom.nMasterId ) // itself is following a master colorscheme
2591 {
2592 auto nOrigMasterId = pMasterPersist->aSlideAtom.nMasterId;
2593 sal_uInt16 nNextMaster = m_pMasterPages->FindPage(nOrigMasterId);
2594 if (nNextMaster == PPTSLIDEPERSIST_ENTRY_NOTFOUND)
2595 break;
2596 pMasterPersist = &(*pPageList2)[ nNextMaster ];
2597 if (pMasterPersist->aSlideAtom.nMasterId == nOrigMasterId)
2598 {
2599 SAL_WARN("filter.ms", "loop in atom chain");
2600 break;
2601 }
2602 }
2603 const_cast<SdrPowerPointImport*>(this)->m_aPageColors = pMasterPersist->aColorScheme;
2604 }
2605 }
2606 }
2607 // register current color scheme
2608 const_cast<SdrPowerPointImport*>(this)->m_nPageColorsNum = m_nCurrentPageNum;
2609 const_cast<SdrPowerPointImport*>(this)->m_ePageColorsKind = m_eCurrentPageKind;
2610 }
2611 rColor = m_aPageColors.GetColor( nNum );
2612 return true;
2613 }
2614
SeekToShape(SvStream & rSt,SvxMSDffClientData * pClientData,sal_uInt32 nId) const2615 bool SdrPowerPointImport::SeekToShape( SvStream& rSt, SvxMSDffClientData* pClientData, sal_uInt32 nId ) const
2616 {
2617 bool bRet = SvxMSDffManager::SeekToShape( rSt, pClientData, nId );
2618 if (!bRet && pClientData)
2619 {
2620 ProcessData& rData = *static_cast<ProcessData*>(pClientData);
2621 PptSlidePersistEntry& rPersistEntry = rData.rPersistEntry;
2622 if ( rPersistEntry.ePageKind == PPT_SLIDEPAGE )
2623 {
2624 if ( HasMasterPage( m_nCurrentPageNum, m_eCurrentPageKind ) )
2625 {
2626 sal_uInt16 nMasterNum = GetMasterPageIndex( m_nCurrentPageNum, m_eCurrentPageKind );
2627 PptSlidePersistList* pPageList = GetPageList( PPT_MASTERPAGE );
2628 if ( pPageList && ( nMasterNum < pPageList->size() ) )
2629 {
2630 assert( !pPageList->is_null( nMasterNum ) );
2631 const PptSlidePersistEntry& rPersist = (*pPageList)[ nMasterNum ]; // get the masterpage's persistentry
2632 if ( rPersist.pPresentationObjects )
2633 {
2634 sal_uInt32 nCurrent(0);
2635 DffRecordList* pCList = maShapeRecords.pCList; // we got a backup of the current position
2636 if ( pCList )
2637 nCurrent = pCList->nCurrent;
2638 if ( const_cast<SdrPowerPointImport*>(this)->maShapeRecords.SeekToContent( rSt, DFF_msofbtClientData, SEEK_FROM_CURRENT_AND_RESTART ) )
2639 {
2640 sal_uInt32 nStreamPos = rSt.Tell();
2641 PPTTextObj aTextObj( rSt, const_cast<SdrPowerPointImport&>(*this), rPersistEntry, nullptr );
2642 if ( aTextObj.Count() || aTextObj.GetOEPlaceHolderAtom() )
2643 {
2644 sal_uInt32 nShapePos = 0;
2645 switch ( aTextObj.GetInstance() )
2646 {
2647 case TSS_Type::Title :
2648 nShapePos = rPersist.pPresentationObjects[ int(TSS_Type::PageTitle) ];
2649 break;
2650 case TSS_Type::PageTitle :
2651 nShapePos = rPersist.pPresentationObjects[ int(TSS_Type::PageTitle) ];
2652 break;
2653 case TSS_Type::Subtitle :
2654 case TSS_Type::HalfBody :
2655 case TSS_Type::QuarterBody :
2656 case TSS_Type::Body :
2657 nShapePos = rPersist.pPresentationObjects[ int(TSS_Type::Body) ];
2658 break;
2659 default: break;
2660 }
2661 if ( nShapePos )
2662 {
2663 rSt.Seek( nShapePos );
2664 bRet = true;
2665 }
2666 }
2667 if ( !bRet )
2668 rSt.Seek( nStreamPos );
2669 }
2670 if ( pCList ) // restoring
2671 pCList->nCurrent = nCurrent;
2672 const_cast<SdrPowerPointImport*>(this)->maShapeRecords.pCList = pCList;
2673 }
2674 }
2675 }
2676 }
2677 }
2678 return bRet;
2679 }
2680
MakeBlankPage(bool bMaster) const2681 rtl::Reference<SdrPage> SdrPowerPointImport::MakeBlankPage( bool bMaster ) const
2682 {
2683 rtl::Reference<SdrPage> pRet = pSdrModel->AllocPage( bMaster );
2684 pRet->SetSize( GetPageSize() );
2685
2686 return pRet;
2687 }
2688
ImportComment10(SvxMSDffManager const & rMan,SvStream & rStCtrl,SdrPage * pPage,DffRecordHeader const & rComment10Hd)2689 static void ImportComment10( SvxMSDffManager const & rMan, SvStream& rStCtrl, SdrPage* pPage, DffRecordHeader const & rComment10Hd )
2690 {
2691 OUString sAuthor;
2692 OUString sText;
2693 OUString sInitials;
2694
2695 sal_Int32 nIndex = 0;
2696 util::DateTime aDateTime;
2697 sal_Int32 nPosX = 0;
2698 sal_Int32 nPosY = 0;
2699
2700
2701 auto nEndRecPos = DffPropSet::SanitizeEndPos(rStCtrl, rComment10Hd.GetRecEndFilePos());
2702 while ( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( rStCtrl.Tell() < nEndRecPos ) )
2703 {
2704 DffRecordHeader aCommentHd;
2705 ReadDffRecordHeader( rStCtrl, aCommentHd );
2706 switch( aCommentHd.nRecType )
2707 {
2708 case PPT_PST_CString :
2709 {
2710 OUString aString = SvxMSDffManager::MSDFFReadZString( rStCtrl,
2711 aCommentHd.nRecLen, true );
2712 switch ( aCommentHd.nRecInstance )
2713 {
2714 case 0 : sAuthor = aString; break;
2715 case 1 : sText = aString; break;
2716 case 2 : sInitials = aString; break;
2717 }
2718 }
2719 break;
2720
2721 case PPT_PST_CommentAtom10 :
2722 {
2723 sal_uInt16 millisec = 0;
2724 rStCtrl.ReadInt32( nIndex )
2725 .ReadInt16( aDateTime.Year )
2726 .ReadUInt16( aDateTime.Month )
2727 .ReadUInt16( aDateTime.Day ) // DayOfWeek
2728 .ReadUInt16( aDateTime.Day )
2729 .ReadUInt16( aDateTime.Hours )
2730 .ReadUInt16( aDateTime.Minutes )
2731 .ReadUInt16( aDateTime.Seconds )
2732 .ReadUInt16( millisec )
2733 .ReadInt32( nPosX )
2734 .ReadInt32( nPosY );
2735
2736 aDateTime.NanoSeconds = millisec * ::tools::Time::nanoPerMilli;
2737 }
2738 break;
2739 }
2740 if (!aCommentHd.SeekToEndOfRecord(rStCtrl))
2741 break;
2742 }
2743 Point aPosition( nPosX, nPosY );
2744 rMan.Scale( aPosition );
2745
2746 try
2747 {
2748 uno::Reference< office::XAnnotationAccess > xAnnotationAccess( pPage->getUnoPage(), UNO_QUERY_THROW );
2749 uno::Reference< office::XAnnotation > xAnnotation( xAnnotationAccess->createAndInsertAnnotation() );
2750 xAnnotation->setPosition( geometry::RealPoint2D( aPosition.X() / 100.0, aPosition.Y() / 100.0 ) );
2751 xAnnotation->setAuthor( sAuthor );
2752 xAnnotation->setDateTime( aDateTime );
2753 xAnnotation->setInitials( sInitials );
2754 uno::Reference< text::XText > xText( xAnnotation->getTextRange() );
2755 xText->setString( sText );
2756 }
2757 catch( const uno::Exception& )
2758 {
2759
2760 }
2761 }
2762
2763
2764 // be sure not to import masterpages with this method
ImportPage(SdrPage * pRet,const PptSlidePersistEntry * pMasterPersist)2765 void SdrPowerPointImport::ImportPage( SdrPage* pRet, const PptSlidePersistEntry* pMasterPersist )
2766 {
2767 sal_uInt32 nOldPos = rStCtrl.Tell();
2768 PptSlidePersistList* pList = GetPageList( m_eCurrentPageKind );
2769 if ( ( !pList ) || ( pList->size() <= m_nCurrentPageNum ) )
2770 return;
2771 PptSlidePersistEntry& rSlidePersist = (*pList)[ m_nCurrentPageNum ];
2772 if ( rSlidePersist.bStarDrawFiller )
2773 return;
2774
2775 DffRecordHeader aPageHd;
2776 if ( SeekToCurrentPage( &aPageHd ) )
2777 {
2778 rSlidePersist.xHeaderFooterEntry.reset(new HeaderFooterEntry(pMasterPersist));
2779 ProcessData aProcessData( rSlidePersist, SdPageCapsule(pRet) );
2780 auto nEndRecPos = SanitizeEndPos(rStCtrl, aPageHd.GetRecEndFilePos());
2781 while ( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( rStCtrl.Tell() < nEndRecPos ) )
2782 {
2783 DffRecordHeader aHd;
2784 ReadDffRecordHeader( rStCtrl, aHd );
2785 switch ( aHd.nRecType )
2786 {
2787 case PPT_PST_HeadersFooters :
2788 {
2789 ImportHeaderFooterContainer(aHd, *rSlidePersist.xHeaderFooterEntry);
2790 }
2791 break;
2792
2793 case PPT_PST_ProgTags :
2794 {
2795 DffRecordHeader aContentDataHd;
2796 if ( SeekToContentOfProgTag( 10, rStCtrl, aHd, aContentDataHd ) )
2797 {
2798 DffRecordHeader aComment10Hd;
2799 while( ( rStCtrl.GetError() == ERRCODE_NONE ) && SeekToRec( rStCtrl, PPT_PST_Comment10, aContentDataHd.GetRecEndFilePos(), &aComment10Hd ) )
2800 {
2801 ImportComment10( *this, rStCtrl, pRet, aComment10Hd );
2802 if (!aComment10Hd.SeekToEndOfRecord(rStCtrl))
2803 break;
2804 }
2805 }
2806 }
2807 break;
2808
2809 case PPT_PST_PPDrawing :
2810 {
2811 DffRecordHeader aPPDrawHd;
2812 if ( SeekToRec( rStCtrl, DFF_msofbtDgContainer, aHd.GetRecEndFilePos(), &aPPDrawHd ) )
2813 {
2814 sal_uInt32 nPPDrawOfs = rStCtrl.Tell();
2815
2816 // importing the background object before importing the page
2817 auto nPPEndRecPos = SanitizeEndPos(rStCtrl, aPPDrawHd.GetRecEndFilePos());
2818 while ( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( rStCtrl.Tell() < nPPEndRecPos ) )
2819 {
2820 DffRecordHeader aEscherObjListHd;
2821 ReadDffRecordHeader( rStCtrl, aEscherObjListHd );
2822 switch ( aEscherObjListHd.nRecType )
2823 {
2824 case DFF_msofbtSpContainer :
2825 {
2826 tools::Rectangle aPageSize( Point(), pRet->GetSize() );
2827 if ( rSlidePersist.aSlideAtom.nFlags & 4 ) // follow master background?
2828 {
2829 if ( HasMasterPage( m_nCurrentPageNum, m_eCurrentPageKind ) )
2830 {
2831 sal_uInt16 nMasterNum = GetMasterPageIndex( m_nCurrentPageNum, m_eCurrentPageKind );
2832 PptSlidePersistList* pPageList = GetPageList( PPT_MASTERPAGE );
2833 PptSlidePersistEntry* pE = &(*pPageList)[ nMasterNum ];
2834 while( ( pE->aSlideAtom.nFlags & 4 ) && pE->aSlideAtom.nMasterId )
2835 {
2836 auto nOrigMasterId = pE->aSlideAtom.nMasterId;
2837 sal_uInt16 nNextMaster = m_pMasterPages->FindPage(nOrigMasterId);
2838 if ( nNextMaster == PPTSLIDEPERSIST_ENTRY_NOTFOUND )
2839 break;
2840 else
2841 pE = &(*pPageList)[ nNextMaster ];
2842 if (pE->aSlideAtom.nMasterId == nOrigMasterId)
2843 {
2844 SAL_WARN("filter.ms", "loop in atom chain");
2845 break;
2846 }
2847 }
2848 if ( pE->nBackgroundOffset )
2849 {
2850 // do not follow master colorscheme?
2851 sal_uInt32 nPos = rStCtrl.Tell();
2852 rStCtrl.Seek( pE->nBackgroundOffset );
2853 rSlidePersist.pBObj = ImportObj( rStCtrl, aProcessData, aPageSize, aPageSize, /*nCalledByGroup*/0, /*pShapeId*/nullptr );
2854 rStCtrl.Seek( nPos );
2855 }
2856 }
2857 }
2858 else
2859 {
2860 DffRecordHeader aShapeHd;
2861 ReadDffRecordHeader( rStCtrl, aShapeHd );
2862 if ( aShapeHd.nRecType == DFF_msofbtSp )
2863 {
2864 sal_uInt32 nSpFlags;
2865 rStCtrl.ReadUInt32( nSpFlags ).ReadUInt32( nSpFlags );
2866 if ( ShapeFlag(nSpFlags) & ShapeFlag::Background )
2867 {
2868 aEscherObjListHd.SeekToBegOfRecord( rStCtrl );
2869 rSlidePersist.pBObj = ImportObj( rStCtrl, aProcessData, aPageSize, aPageSize, /*nCalledByGroup*/0, /*pShapeId*/nullptr );
2870 }
2871 }
2872 }
2873 }
2874 break;
2875 }
2876 if ( aEscherObjListHd.nRecType == DFF_msofbtSpContainer )
2877 break;
2878 if (!aEscherObjListHd.SeekToEndOfRecord(rStCtrl))
2879 break;
2880 }
2881
2882 // now importing page
2883 rStCtrl.Seek( nPPDrawOfs );
2884 auto nHdEndRecPos = SanitizeEndPos(rStCtrl, aPPDrawHd.GetRecEndFilePos());
2885 while ( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( rStCtrl.Tell() < nHdEndRecPos ) )
2886 {
2887 DffRecordHeader aEscherObjListHd;
2888 ReadDffRecordHeader( rStCtrl, aEscherObjListHd );
2889 switch ( aEscherObjListHd.nRecType )
2890 {
2891 case DFF_msofbtSpgrContainer :
2892 {
2893 DffRecordHeader aShapeHd;
2894 if ( SeekToRec( rStCtrl, DFF_msofbtSpContainer, aEscherObjListHd.GetRecEndFilePos(), &aShapeHd ) )
2895 {
2896 if (!aShapeHd.SeekToEndOfRecord(rStCtrl))
2897 {
2898 break;
2899 }
2900 auto nListEndRecPos = SanitizeEndPos(rStCtrl, aEscherObjListHd.GetRecEndFilePos());
2901 while ( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( rStCtrl.Tell() < nListEndRecPos ) )
2902 {
2903 ReadDffRecordHeader( rStCtrl, aShapeHd );
2904 if ( ( aShapeHd.nRecType == DFF_msofbtSpContainer ) || ( aShapeHd.nRecType == DFF_msofbtSpgrContainer ) )
2905 {
2906 tools::Rectangle aEmpty;
2907 aShapeHd.SeekToBegOfRecord( rStCtrl );
2908 sal_Int32 nShapeId;
2909 aProcessData.pTableRowProperties.reset();
2910 SdrObject* pObj = ImportObj( rStCtrl, aProcessData, aEmpty, aEmpty, 0, &nShapeId );
2911 if ( pObj )
2912 {
2913 if ( aProcessData.pTableRowProperties )
2914 pObj = CreateTable(pObj, aProcessData.pTableRowProperties.get(), aProcessData.rPersistEntry.xSolverContainer.get(), aProcessData.aBackgroundColoredObjects);
2915
2916 pRet->NbcInsertObject( pObj );
2917
2918 if( nShapeId )
2919 insertShapeId( nShapeId, pObj );
2920 }
2921 }
2922 bool bSuccess = aShapeHd.SeekToEndOfRecord(rStCtrl);
2923 if (!bSuccess)
2924 break;
2925 }
2926 }
2927 }
2928 break;
2929 }
2930 if ( aEscherObjListHd.nRecType == DFF_msofbtSpgrContainer )
2931 break;
2932 if (!aEscherObjListHd.SeekToEndOfRecord(rStCtrl))
2933 break;
2934 }
2935
2936 // Handle shapes where the fill matches the background
2937 // fill (mso_fillBackground).
2938 if (rSlidePersist.ePageKind == PPT_SLIDEPAGE)
2939 {
2940 if (!aProcessData.aBackgroundColoredObjects.empty())
2941 {
2942 if (!rSlidePersist.pBObj)
2943 {
2944 for (auto pObject : aProcessData.aBackgroundColoredObjects)
2945 {
2946 // The shape wants a background, but the slide doesn't have
2947 // one: default to white.
2948 SfxItemSet aNewSet(*pObject->GetMergedItemSet().GetPool());
2949 aNewSet.Put(XFillStyleItem(css::drawing::FillStyle_SOLID));
2950 aNewSet.Put(XFillColorItem(OUString(), COL_WHITE));
2951 pObject->SetMergedItemSet(aNewSet);
2952 }
2953 }
2954 }
2955 }
2956
2957 if ( rSlidePersist.pBObj )
2958 {
2959 // #i99386# transfer the attributes from the temporary BackgroundObject
2960 // to the Page and delete it.
2961 pRet->getSdrPageProperties().ClearItem();
2962 pRet->getSdrPageProperties().PutItemSet(rSlidePersist.pBObj->GetMergedItemSet());
2963 if (rSlidePersist.xSolverContainer)
2964 {
2965 for (auto & pPtr : rSlidePersist.xSolverContainer->aCList)
2966 {
2967 // check connections to the group object
2968 if (pPtr->pAObj == rSlidePersist.pBObj)
2969 pPtr->pAObj = nullptr;
2970 if (pPtr->pBObj == rSlidePersist.pBObj)
2971 pPtr->pBObj = nullptr;
2972 if (pPtr->pCObj == rSlidePersist.pBObj)
2973 pPtr->pCObj = nullptr;
2974 }
2975 }
2976 SdrObject::Free(rSlidePersist.pBObj);
2977 }
2978 }
2979 }
2980 break;
2981 }
2982 if (!aHd.SeekToEndOfRecord(rStCtrl))
2983 break;
2984 }
2985 if (rSlidePersist.xSolverContainer)
2986 SolveSolver(*rSlidePersist.xSolverContainer);
2987 }
2988 rStCtrl.Seek( nOldPos );
2989 }
2990
GetSlideLayoutAtom() const2991 const PptSlideLayoutAtom* SdrPowerPointImport::GetSlideLayoutAtom() const
2992 {
2993 PptSlidePersistList* pPageList = GetPageList( m_eCurrentPageKind );
2994 if ( pPageList && m_nCurrentPageNum < pPageList->size() )
2995 {
2996 assert( !pPageList->is_null( m_nCurrentPageNum ) );
2997 return &(*pPageList)[ m_nCurrentPageNum ].aSlideAtom.aLayout;
2998 }
2999 return nullptr;
3000 }
3001
IsNoteOrHandout(sal_uInt16 nPageNum) const3002 bool SdrPowerPointImport::IsNoteOrHandout( sal_uInt16 nPageNum ) const
3003 {
3004 bool bNote = m_eCurrentPageKind == PPT_NOTEPAGE;
3005 if ( m_eCurrentPageKind == PPT_MASTERPAGE )
3006 bNote = ( nPageNum & 1 ) == 0;
3007 return bNote;
3008 }
3009
GetMasterPageId(sal_uInt16 nPageNum,PptPageKind ePageKind) const3010 sal_uInt32 SdrPowerPointImport::GetMasterPageId( sal_uInt16 nPageNum, PptPageKind ePageKind ) const
3011 {
3012 PptSlidePersistList* pPageList = GetPageList( ePageKind );
3013 if ( pPageList && nPageNum < pPageList->size() )
3014 return (*pPageList)[ nPageNum ].aSlideAtom.nMasterId;
3015 return 0;
3016 }
3017
GetNotesPageId(sal_uInt16 nPageNum) const3018 sal_uInt32 SdrPowerPointImport::GetNotesPageId( sal_uInt16 nPageNum ) const
3019 {
3020 PptSlidePersistList* pPageList=GetPageList( PPT_SLIDEPAGE );
3021 if ( pPageList && nPageNum < pPageList->size() )
3022 return (*pPageList)[ nPageNum ].aSlideAtom.nNotesId;
3023 return 0;
3024 }
3025
HasMasterPage(sal_uInt16 nPageNum,PptPageKind ePageKind) const3026 bool SdrPowerPointImport::HasMasterPage( sal_uInt16 nPageNum, PptPageKind ePageKind ) const
3027 {
3028 if ( ePageKind == PPT_NOTEPAGE )
3029 return aDocAtom.nNotesMasterPersist != 0;
3030 if ( ePageKind == PPT_MASTERPAGE )
3031 return false;
3032 return GetMasterPageId( nPageNum, ePageKind ) != 0;
3033 }
3034
GetMasterPageIndex(sal_uInt16 nPageNum,PptPageKind ePageKind) const3035 sal_uInt16 SdrPowerPointImport::GetMasterPageIndex( sal_uInt16 nPageNum, PptPageKind ePageKind ) const
3036 {
3037 sal_uInt16 nIdx = 0;
3038 if ( ePageKind == PPT_NOTEPAGE )
3039 return 2;
3040 sal_uInt32 nId = GetMasterPageId( nPageNum, ePageKind );
3041 if (nId && m_pMasterPages)
3042 {
3043 nIdx = m_pMasterPages->FindPage( nId );
3044 if ( nIdx == PPTSLIDEPERSIST_ENTRY_NOTFOUND )
3045 nIdx = 0;
3046 }
3047 return nIdx;
3048 }
3049
ImportPageBackgroundObject(const SdrPage & rPage,sal_uInt32 & nBgFileOffset)3050 SdrObject* SdrPowerPointImport::ImportPageBackgroundObject( const SdrPage& rPage, sal_uInt32& nBgFileOffset )
3051 {
3052 SdrObject* pRet = nullptr;
3053 std::unique_ptr<SfxItemSet> pSet;
3054 sal_uLong nOldFPos = rStCtrl.Tell(); // remember FilePos for restoring it later
3055 DffRecordHeader aPageHd;
3056 if ( SeekToCurrentPage( &aPageHd ) )
3057 { // and now search for the background attributes of the Page
3058 sal_uLong nPageRecEnd = aPageHd.GetRecEndFilePos();
3059 DffRecordHeader aPPDrawHd;
3060 if ( SeekToRec( rStCtrl, PPT_PST_PPDrawing, nPageRecEnd, &aPPDrawHd ) )
3061 {
3062 sal_uLong nPPDrawEnd = aPPDrawHd.GetRecEndFilePos();
3063 DffRecordHeader aEscherF002Hd;
3064 if ( SeekToRec( rStCtrl, DFF_msofbtDgContainer, nPPDrawEnd, &aEscherF002Hd ) )
3065 {
3066 sal_uLong nEscherF002End = aEscherF002Hd.GetRecEndFilePos();
3067 DffRecordHeader aEscherObjectHd;
3068 if ( SeekToRec( rStCtrl, DFF_msofbtSpContainer, nEscherF002End, &aEscherObjectHd ) )
3069 {
3070 nBgFileOffset = aEscherObjectHd.GetRecBegFilePos();
3071 //sal_uLong nEscherObjectEnd = aEscherObjectHd.GetRecEndFilePos();
3072 //DffRecordHeader aEscherPropertiesHd;
3073 if ( SeekToRec( rStCtrl, DFF_msofbtOPT,nEscherF002End ) )
3074 {
3075 ReadDffPropSet( rStCtrl, static_cast<DffPropertyReader&>(*this) );
3076 mnFix16Angle = Fix16ToAngle( GetPropertyValue( DFF_Prop_Rotation, 0 ) );
3077 sal_uInt32 nColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff );
3078 pSet.reset(new SfxItemSet( pSdrModel->GetItemPool() ));
3079 DffObjData aObjData( aEscherObjectHd, tools::Rectangle( 0, 0, 28000, 21000 ), 0 );
3080 ApplyAttributes( rStCtrl, *pSet, aObjData );
3081 Color aColor( MSO_CLR_ToColor( nColor ) );
3082 pSet->Put( XFillColorItem( OUString(), aColor ) );
3083 }
3084 }
3085 }
3086 }
3087 }
3088 rStCtrl.Seek( nOldFPos ); // restore FilePos
3089 if ( !pSet )
3090 {
3091 pSet.reset(new SfxItemSet( pSdrModel->GetItemPool() ));
3092 pSet->Put( XFillStyleItem( drawing::FillStyle_NONE ) );
3093 }
3094 pSet->Put( XLineStyleItem( drawing::LineStyle_NONE ) );
3095 tools::Rectangle aRect(
3096 rPage.GetLeftBorder(),
3097 rPage.GetUpperBorder(),
3098 rPage.GetWidth() - rPage.GetRightBorder(),
3099 rPage.GetHeight() - rPage.GetLowerBorder());
3100
3101 pRet = new SdrRectObj(
3102 *pSdrModel,
3103 aRect);
3104
3105 pRet->SetMergedItemSet(*pSet);
3106 pRet->SetMarkProtect( true );
3107 pRet->SetMoveProtect( true );
3108 pRet->SetResizeProtect( true );
3109 return pRet;
3110 }
3111
HeaderFooterEntry(const PptSlidePersistEntry * pMPE)3112 HeaderFooterEntry::HeaderFooterEntry( const PptSlidePersistEntry* pMPE ) :
3113 pMasterPersist ( pMPE ),
3114 nAtom ( 0 )
3115 {
3116 if ( pMPE )
3117 {
3118 HeaderFooterEntry* pMHFE = pMPE->xHeaderFooterEntry.get();
3119 if ( pMHFE )
3120 {
3121 nAtom = pMPE->xHeaderFooterEntry->nAtom;
3122 pPlaceholder[ 0 ] = pMHFE->pPlaceholder[ 0 ];
3123 pPlaceholder[ 1 ] = pMHFE->pPlaceholder[ 1 ];
3124 pPlaceholder[ 2 ] = pMHFE->pPlaceholder[ 2 ];
3125 pPlaceholder[ 3 ] = pMHFE->pPlaceholder[ 3 ];
3126 }
3127 }
3128 }
3129
IsToDisplay(sal_uInt32 nInstance)3130 sal_uInt32 HeaderFooterEntry::IsToDisplay( sal_uInt32 nInstance )
3131 {
3132 sal_uInt32 nMask = 0;
3133 switch ( nInstance )
3134 {
3135 case 0 : nMask = 0x010000; break;
3136 case 1 : nMask = 0x100000; break;
3137 case 2 : nMask = 0x200000; break;
3138 case 3 : nMask = 0x080000; break;
3139 }
3140 return ( nAtom & nMask );
3141 }
3142
3143 // The following method checks if the slide is using a different colorscheme than
3144 // its master, if this is the fact, then the HeaderFooter must probably be
3145 // imported as real sdrobject. In this case, the return value is the offset to the
3146 // master header footer object, so it can be re-loaded with a different color set
NeedToImportInstance(const sal_uInt32 nInstance,const PptSlidePersistEntry & rSlidePersist)3147 sal_uInt32 HeaderFooterEntry::NeedToImportInstance( const sal_uInt32 nInstance, const PptSlidePersistEntry& rSlidePersist )
3148 {
3149 sal_uInt32 nRet = 0;
3150 if ( pMasterPersist )
3151 {
3152 if ( !( rSlidePersist.aSlideAtom.nFlags & 2 ) )
3153 { // not following the master persist, so we have to check if the colors are changed
3154 if ( memcmp( &rSlidePersist.aColorScheme, &pMasterPersist->aColorScheme, 32 ) )
3155 {
3156 nRet = pMasterPersist->HeaderFooterOfs[ nInstance ];
3157 }
3158 }
3159 }
3160 return nRet;
3161 }
3162
ImportHeaderFooterContainer(DffRecordHeader const & rHd,HeaderFooterEntry & rE)3163 void SdrEscherImport::ImportHeaderFooterContainer( DffRecordHeader const & rHd, HeaderFooterEntry& rE )
3164 {
3165 rHd.SeekToContent( rStCtrl );
3166 auto nEndRecPos = SanitizeEndPos(rStCtrl, rHd.GetRecEndFilePos());
3167 while ( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( rStCtrl.Tell() < nEndRecPos ) )
3168 {
3169 DffRecordHeader aHd;
3170 ReadDffRecordHeader( rStCtrl, aHd );
3171 switch ( aHd.nRecType )
3172 {
3173 case PPT_PST_HeadersFootersAtom :
3174 rStCtrl.ReadUInt32( rE.nAtom );
3175 break;
3176
3177 case PPT_PST_CString :
3178 {
3179 if ( aHd.nRecInstance < 4 )
3180 {
3181 rE.pPlaceholder[ aHd.nRecInstance ] = MSDFFReadZString( rStCtrl,
3182 aHd.nRecLen, true );
3183 }
3184 }
3185 break;
3186 }
3187 if (!aHd.SeekToEndOfRecord(rStCtrl))
3188 break;
3189 }
3190 }
3191
PPTBuGraEntry(Graphic const & rGraphic,sal_uInt32 nInst)3192 PPTBuGraEntry::PPTBuGraEntry( Graphic const & rGraphic, sal_uInt32 nInst ) :
3193 nInstance ( nInst ),
3194 aBuGra ( rGraphic ) {}
3195
PPTExtParaLevel()3196 PPTExtParaLevel::PPTExtParaLevel()
3197 : mnExtParagraphMask( 0 )
3198 , mnBuBlip( 0xffff )
3199 , mnHasAnm( 0 )
3200 , mnAnmScheme( 0 )
3201 , mpfPP10Ext( 0 )
3202 , mnExtCharacterMask( 0 )
3203 , mcfPP10Ext( 0 )
3204 , mbSet( false )
3205 {}
3206
ReadPPTExtParaLevel(SvStream & rIn,PPTExtParaLevel & rLevel)3207 SvStream& ReadPPTExtParaLevel( SvStream& rIn, PPTExtParaLevel& rLevel )
3208 {
3209 rLevel.mbSet = true;
3210 rIn.ReadUInt32( rLevel.mnExtParagraphMask );
3211 if ( rLevel.mnExtParagraphMask & 0x00800000 )
3212 rIn.ReadUInt16( rLevel.mnBuBlip );
3213 if ( rLevel.mnExtParagraphMask & 0x02000000 )
3214 rIn.ReadUInt16( rLevel.mnHasAnm );
3215 if ( rLevel.mnExtParagraphMask & 0x01000000 )
3216 rIn.ReadUInt32( rLevel.mnAnmScheme );
3217 if ( rLevel.mnExtParagraphMask & 0x04000000 )
3218 rIn.ReadUInt32( rLevel.mpfPP10Ext );
3219 rIn.ReadUInt32( rLevel.mnExtCharacterMask );
3220 if ( rLevel.mnExtCharacterMask & 0x100000 )
3221 rIn.ReadUInt32( rLevel.mcfPP10Ext );
3222 return rIn;
3223 }
3224
GetGraphic(sal_uInt32 nInstance,Graphic & rGraph) const3225 bool PPTExtParaProv::GetGraphic( sal_uInt32 nInstance, Graphic& rGraph ) const
3226 {
3227 bool bRetValue = false;
3228 PPTBuGraEntry* pPtr = nullptr;
3229 if ( nInstance < aBuGraList.size() )
3230 {
3231 pPtr = aBuGraList[ nInstance ].get();
3232 if ( pPtr->nInstance == nInstance )
3233 bRetValue = true;
3234 }
3235 if ( !bRetValue )
3236 {
3237 for (std::unique_ptr<PPTBuGraEntry> const & i : aBuGraList)
3238 {
3239 pPtr = i.get();
3240 if ( pPtr->nInstance == nInstance )
3241 {
3242 bRetValue = true;
3243 break;
3244 }
3245 }
3246 }
3247 if ( bRetValue )
3248 rGraph = pPtr->aBuGra;
3249 return bRetValue;
3250 }
3251
PPTExtParaProv(SdrPowerPointImport & rMan,SvStream & rSt,const DffRecordHeader * pHd)3252 PPTExtParaProv::PPTExtParaProv( SdrPowerPointImport& rMan, SvStream& rSt, const DffRecordHeader* pHd ) :
3253 bStyles ( false )
3254 {
3255 sal_uInt32 nOldPos = rSt.Tell();
3256
3257 // here we have to get the graphical bullets...
3258
3259 DffRecordHeader aHd;
3260 DffRecordHeader aContentDataHd;
3261
3262 const DffRecordHeader* pListHd = rMan.aDocRecManager.GetRecordHeader( PPT_PST_List );
3263 if( pListHd )
3264 pListHd->SeekToContent( rSt );
3265 if ( pListHd && SdrPowerPointImport::SeekToContentOfProgTag( 9, rSt, *pListHd, aContentDataHd ) )
3266 {
3267 auto nEndRecPos = DffPropSet::SanitizeEndPos(rSt, aContentDataHd.GetRecEndFilePos());
3268 while ( ( rSt.GetError() == ERRCODE_NONE ) && ( rSt.Tell() < nEndRecPos ) )
3269 {
3270 ReadDffRecordHeader( rSt, aHd );
3271 switch ( aHd.nRecType )
3272 {
3273 case PPT_PST_ExtendedBuGraContainer :
3274 {
3275 auto nHdEndRecPos = DffPropSet::SanitizeEndPos(rSt, aHd.GetRecEndFilePos());
3276 while ( ( rSt.GetError() == ERRCODE_NONE ) && ( rSt.Tell() < nHdEndRecPos ) )
3277 {
3278 DffRecordHeader aBuGraAtomHd;
3279 ReadDffRecordHeader( rSt, aBuGraAtomHd );
3280 if ( aBuGraAtomHd.nRecType == PPT_PST_ExtendedBuGraAtom )
3281 {
3282 sal_uInt16 nType;
3283 rSt.ReadUInt16( nType );
3284 Graphic aGraphic;
3285 if ( SvxMSDffManager::GetBLIPDirect( rSt, aGraphic ) )
3286 {
3287 sal_uInt32 nInstance = aBuGraAtomHd.nRecInstance;
3288 PPTBuGraEntry* pBuGra = new PPTBuGraEntry( aGraphic, nInstance );
3289 size_t n = 0;
3290 size_t nBuGraCount = aBuGraList.size();
3291 if ( nBuGraCount )
3292 {
3293 if ( aBuGraList[ nBuGraCount - 1 ]->nInstance < nInstance )
3294 n = nBuGraCount;
3295 else
3296 { // maybe the instances are not sorted, we sort it
3297 for ( n = 0; n < nBuGraCount; n++ )
3298 { // sorting fields ( hi >> lo )
3299 if ( aBuGraList[ n ]->nInstance < nInstance )
3300 break;
3301 }
3302 }
3303 }
3304 if ( n < nBuGraCount ) {
3305 aBuGraList.emplace( aBuGraList.begin() + n, pBuGra );
3306 } else {
3307 aBuGraList.emplace_back( pBuGra );
3308 }
3309 }
3310 #ifdef DBG_UTIL
3311 else OSL_FAIL( "PPTExParaProv::PPTExParaProv - bullet graphic is not valid (SJ)" );
3312 #endif
3313 }
3314 #ifdef DBG_UTIL
3315 else OSL_FAIL( "PPTExParaProv::PPTExParaProv - unknown atom interpreting the PPT_PST_ExtendedBuGraContainer (SJ)" );
3316 #endif
3317 if (!aBuGraAtomHd.SeekToEndOfRecord(rSt))
3318 break;
3319 }
3320 }
3321 break;
3322
3323 case PPT_PST_ExtendedPresRuleContainer :
3324 aExtendedPresRules.Consume( rSt, aHd.GetRecEndFilePos() );
3325 break;
3326 #ifdef DBG_UTIL
3327 default :
3328 OSL_FAIL( "PPTExParaProv::PPTExParaProv - unknown atom reading ppt2000 num rules (SJ)" );
3329 break;
3330 case PPT_PST_MasterText : // first seen in: ms-tt02.ppt
3331 case PPT_PST_SrKinsoku :
3332 case PPT_PST_TextDefaults9Atom :
3333 case PPT_PST_PresentationAdvisorFlags9Atom :
3334 case PPT_PST_HtmlDocInfo9Atom :
3335 case PPT_PST_GridSpacing10Atom :
3336 case PPT_PST_CommentIndex10 :
3337 case PPT_PST_DocToolbarStates10Atom :
3338 break;
3339 #endif
3340 }
3341 if (!aHd.SeekToEndOfRecord(rSt))
3342 break;
3343 }
3344 }
3345
3346 if ( pHd && SdrPowerPointImport::SeekToContentOfProgTag( 9, rSt, *pHd, aContentDataHd ) )
3347 { // get the extended paragraph styles on mainmaster ( graphical bullets, num ruling ... )
3348 auto nEndRecPos = DffPropSet::SanitizeEndPos(rSt, aContentDataHd.GetRecEndFilePos());
3349 while ( ( rSt.GetError() == ERRCODE_NONE ) && ( rSt.Tell() < nEndRecPos ) )
3350 {
3351 ReadDffRecordHeader( rSt, aHd );
3352 switch ( aHd.nRecType )
3353 {
3354 case PPT_PST_ExtendedParagraphMasterAtom :
3355 {
3356 if ( aHd.nRecInstance < PPT_STYLESHEETENTRIES )
3357 {
3358 sal_uInt16 nDepth = 0, i = 0;
3359 rSt.ReadUInt16(nDepth);
3360 nDepth = std::min<sal_uInt16>(nDepth, nMaxPPTLevels);
3361 auto nHdEndRecPos = DffPropSet::SanitizeEndPos(rSt, aHd.GetRecEndFilePos());
3362 while ( ( rSt.GetError() == ERRCODE_NONE ) && ( rSt.Tell() < nHdEndRecPos ) && ( i < nDepth ) )
3363 {
3364 bStyles = true;
3365 ReadPPTExtParaLevel( rSt, aExtParaSheet[ static_cast<TSS_Type>(aHd.nRecInstance) ].aExtParaLevel[ i++ ] );
3366 }
3367 #ifdef DBG_UTIL
3368 if ( rSt.Tell() != aHd.GetRecEndFilePos() )
3369 OSL_FAIL( "PPTExParaProv::PPTExParaProv - error reading PPT_PST_ExtendedParagraphMasterAtom (SJ)" );
3370 #endif
3371 }
3372 #ifdef DBG_UTIL
3373 else OSL_FAIL( "PPTExParaProv::PPTExParaProv - instance out of range (SJ)" );
3374 #endif
3375 }
3376 break;
3377 default :
3378 OSL_FAIL( "PPTExParaProv::PPTExParaProv - unknown atom, assuming PPT_PST_ExtendedParagraphMasterAtom (SJ)" );
3379 break;
3380 case PPT_PST_HashCodeAtom :
3381 case PPT_PST_BuildList :
3382 case PPT_PST_SlideFlags10Atom :
3383 case PPT_PST_SlideTime10Atom :
3384 case 0xf144 :
3385 break;
3386 }
3387 if (!aHd.SeekToEndOfRecord(rSt))
3388 break;
3389 }
3390 }
3391 rSt.Seek( nOldPos );
3392 }
3393
~PPTExtParaProv()3394 PPTExtParaProv::~PPTExtParaProv()
3395 {
3396 }
3397
PPTNumberFormatCreator(std::unique_ptr<PPTExtParaProv> pParaProv)3398 PPTNumberFormatCreator::PPTNumberFormatCreator( std::unique_ptr<PPTExtParaProv> pParaProv )
3399 : nIsBullet(0)
3400 , nBulletChar(0)
3401 , nBulletFont(0)
3402 , nBulletHeight(0)
3403 , nBulletColor(0)
3404 , nTextOfs(0)
3405 , nBulletOfs(0)
3406 , pExtParaProv(std::move(pParaProv))
3407 {
3408 }
3409
~PPTNumberFormatCreator()3410 PPTNumberFormatCreator::~PPTNumberFormatCreator()
3411 {
3412 }
3413
ImplGetExtNumberFormat(SdrPowerPointImport const & rManager,SvxNumberFormat & rNumberFormat,sal_uInt32 nLevel,TSS_Type nInstance,TSS_Type nDestinationInstance,std::optional<sal_Int16> & rStartNumbering,sal_uInt32 nFontHeight,PPTParagraphObj const * pPara)3414 bool PPTNumberFormatCreator::ImplGetExtNumberFormat( SdrPowerPointImport const & rManager,
3415 SvxNumberFormat& rNumberFormat, sal_uInt32 nLevel, TSS_Type nInstance, TSS_Type nDestinationInstance,
3416 std::optional< sal_Int16 >& rStartNumbering, sal_uInt32 nFontHeight, PPTParagraphObj const * pPara )
3417 {
3418 bool bHardAttribute = ( nDestinationInstance == TSS_Type::Unknown );
3419
3420 sal_uInt32 nBuFlags = 0;
3421 sal_uInt16 nHasAnm = 0;
3422 sal_uInt32 nAnmScheme = 0xFFFF0003;
3423 sal_uInt16 nBuBlip = 0xffff;
3424
3425 const PPTExtParaProv* pParaProv = pExtParaProv.get();
3426 if ( !pExtParaProv )
3427 pParaProv = pPara ? pPara->mrStyleSheet.pExtParaProv.get()
3428 : rManager.m_pPPTStyleSheet->pExtParaProv.get();
3429 if ( pPara )
3430 {
3431 nBuFlags = pPara->mxParaSet->mnExtParagraphMask;
3432 if ( nBuFlags )
3433 {
3434 if ( nBuFlags & 0x00800000 )
3435 nBuBlip = pPara->mxParaSet->mnBuBlip;
3436 if ( nBuFlags & 0x01000000 )
3437 nAnmScheme = pPara->mxParaSet->mnAnmScheme;
3438 if ( nBuFlags & 0x02000000 )
3439 nHasAnm = pPara->mxParaSet->mnHasAnm;
3440 bHardAttribute = true;
3441 }
3442 }
3443
3444 if ( ( nBuFlags & 0x03800000 ) != 0x03800000 ) // merge style sheet
3445 {
3446 // we have to read the master attributes
3447 if (pParaProv && nLevel < nMaxPPTLevels)
3448 {
3449 if ( pParaProv->bStyles )
3450 {
3451 const PPTExtParaLevel& rLev = pParaProv->aExtParaSheet[ nInstance ].aExtParaLevel[ nLevel ];
3452 if ( rLev.mbSet )
3453 {
3454 sal_uInt32 nMaBuFlags = rLev.mnExtParagraphMask;
3455
3456 if ( (!( nBuFlags & 0x00800000)) && ( nMaBuFlags & 0x00800000 ) )
3457 {
3458 if (!( nBuFlags & 0x02000000)) // if there is a BuStart without BuInstance,
3459 nBuBlip = rLev.mnBuBlip; // then there is no graphical Bullet possible
3460 }
3461 if ( (!( nBuFlags & 0x01000000)) && ( nMaBuFlags & 0x01000000 ) )
3462 nAnmScheme = rLev.mnAnmScheme;
3463 if ( (!( nBuFlags & 0x02000000)) && ( nMaBuFlags & 0x02000000 ) )
3464 nHasAnm = rLev.mnHasAnm;
3465 nBuFlags |= nMaBuFlags;
3466 }
3467 }
3468 }
3469 }
3470 if ( nBuBlip != 0xffff ) // set graphical bullet
3471 {
3472 Graphic aGraphic;
3473 if ( pParaProv && pParaProv->GetGraphic( nBuBlip, aGraphic ) )
3474 {
3475 SvxBrushItem aBrush( aGraphic, GPOS_MM, SID_ATTR_BRUSH );
3476 rNumberFormat.SetGraphicBrush( &aBrush );
3477 sal_uInt32 nHeight = static_cast<sal_uInt32>( static_cast<double>(nFontHeight) * 0.2540 * nBulletHeight + 0.5 );
3478 Size aPrefSize( aGraphic.GetPrefSize() );
3479 sal_uInt32 nWidth;
3480 if (aPrefSize.Height())
3481 nWidth = ( nHeight * aPrefSize.Width() ) / aPrefSize.Height();
3482 else
3483 nWidth = 0;
3484 rNumberFormat.SetGraphicSize( Size( nWidth, nHeight ) );
3485 rNumberFormat.SetNumberingType ( SVX_NUM_BITMAP );
3486 }
3487 }
3488 else if ( nHasAnm )
3489 {
3490 switch( static_cast< sal_uInt16 >( nAnmScheme ) )
3491 {
3492 default :
3493 case 0 :
3494 {
3495 rNumberFormat.SetNumberingType( SVX_NUM_CHARS_LOWER_LETTER );
3496 rNumberFormat.SetSuffix( "." );
3497 }
3498 break;
3499 case 1 :
3500 {
3501 rNumberFormat.SetNumberingType( SVX_NUM_CHARS_UPPER_LETTER );
3502 rNumberFormat.SetSuffix( "." );
3503 }
3504 break;
3505 case 2 :
3506 {
3507 rNumberFormat.SetNumberingType( SVX_NUM_ARABIC );
3508 rNumberFormat.SetSuffix( ")" );
3509 }
3510 break;
3511 case 3 :
3512 {
3513 rNumberFormat.SetNumberingType( SVX_NUM_ARABIC );
3514 rNumberFormat.SetSuffix( "." );
3515 }
3516 break;
3517 case 4 :
3518 {
3519 rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_LOWER );
3520 rNumberFormat.SetSuffix( ")" );
3521 rNumberFormat.SetPrefix( "(" );
3522 }
3523 break;
3524 case 5 :
3525 {
3526 rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_LOWER );
3527 rNumberFormat.SetSuffix( ")" );
3528 }
3529 break;
3530 case 6 :
3531 {
3532 rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_LOWER );
3533 rNumberFormat.SetSuffix( "." );
3534 }
3535 break;
3536 case 7 :
3537 {
3538 rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_UPPER );
3539 rNumberFormat.SetSuffix( "." );
3540 }
3541 break;
3542 case 8 :
3543 {
3544 rNumberFormat.SetNumberingType( SVX_NUM_CHARS_LOWER_LETTER );
3545 rNumberFormat.SetSuffix( ")" );
3546 rNumberFormat.SetPrefix( "(" );
3547 }
3548 break;
3549 case 9 :
3550 {
3551 rNumberFormat.SetNumberingType( SVX_NUM_CHARS_LOWER_LETTER );
3552 rNumberFormat.SetSuffix( ")" );
3553 }
3554 break;
3555 case 10 :
3556 {
3557 rNumberFormat.SetNumberingType( SVX_NUM_CHARS_UPPER_LETTER );
3558 rNumberFormat.SetSuffix( ")" );
3559 rNumberFormat.SetPrefix( "(" );
3560 }
3561 break;
3562 case 11 :
3563 {
3564 rNumberFormat.SetNumberingType( SVX_NUM_CHARS_UPPER_LETTER );
3565 rNumberFormat.SetSuffix( ")" );
3566 }
3567 break;
3568 case 12 :
3569 {
3570 rNumberFormat.SetNumberingType( SVX_NUM_ARABIC );
3571 rNumberFormat.SetSuffix( ")" );
3572 rNumberFormat.SetPrefix( "(" );
3573 }
3574 break;
3575 case 13 :
3576 {
3577 rNumberFormat.SetNumberingType( SVX_NUM_ARABIC );
3578 }
3579 break;
3580 case 14 :
3581 {
3582 rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_UPPER );
3583 rNumberFormat.SetSuffix( ")" );
3584 rNumberFormat.SetPrefix( "(" );
3585 }
3586 break;
3587 case 15 :
3588 {
3589 rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_UPPER );
3590 rNumberFormat.SetSuffix( ")" );
3591 }
3592 break;
3593 case 16: // Simplified Chinese.
3594 {
3595 rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_UPPER_ZH );
3596 }
3597 break;
3598 case 17: // Simplified Chinese with single-byte period.
3599 {
3600 rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_UPPER_ZH );
3601 rNumberFormat.SetSuffix( "." );
3602 }
3603 break;
3604 case 18: // Double byte circle numbers.
3605 case 19: // Wingdings white circle numbers.
3606 case 20: // Wingdings black circle numbers.
3607 {
3608 rNumberFormat.SetNumberingType( SVX_NUM_CIRCLE_NUMBER );
3609 }
3610 break;
3611 case 21: // Traditional Chinese.
3612 {
3613 rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_UPPER_ZH_TW );
3614 }
3615 break;
3616 case 22: // Traditional Chinese with single-byte period.
3617 {
3618 rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_UPPER_ZH_TW );
3619 rNumberFormat.SetSuffix( "." );
3620 }
3621 break;
3622 case 25: // Bidi Hebrew 2 with ANSI minus symbol.
3623 {
3624 rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_HEBREW );
3625 rNumberFormat.SetSuffix( "-" );
3626 }
3627 break;
3628 case 26: // Japanese/Korean.
3629 {
3630 rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_LOWER_ZH );
3631 }
3632 break;
3633 case 27: // Japanese/Korean with single-byte period.
3634 {
3635 rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_LOWER_ZH );
3636 rNumberFormat.SetSuffix( "." );
3637 }
3638 break;
3639 case 28: // Double-byte Arabic numbers.
3640 {
3641 rNumberFormat.SetNumberingType( SVX_NUM_FULL_WIDTH_ARABIC );
3642 }
3643 break;
3644 case 29: // Double-byte Arabic numbers with double-byte period.
3645 {
3646 rNumberFormat.SetNumberingType( SVX_NUM_FULL_WIDTH_ARABIC );
3647 rNumberFormat.SetSuffix( OUString( u'\xff0e' ) );
3648 }
3649 break;
3650 case 38: // Japanese with double-byte period.
3651 {
3652 rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_LOWER_ZH ); // No such type. Instead with Lower Chinese Number
3653 rNumberFormat.SetSuffix( OUString( u'\xff0e' ) );
3654 }
3655 break;
3656 }
3657 rStartNumbering = std::optional< sal_Int16 >( nAnmScheme >> 16 );
3658 sal_Int16 nBuStart = *rStartNumbering;
3659 //The Seventh bit of nBuFlags that specifies whether fBulletHasAutoNumber exists,
3660 //and fBulletHasAutoNumber that specifies whether this paragraph has an automatic numbering scheme.
3661 if ( ( nBuFlags & 0x02000000 ) && ( nBuStart != -1 ))
3662 {
3663 rNumberFormat.SetStart( static_cast<sal_uInt16>(nBuStart) );
3664 }
3665 }
3666 return bHardAttribute;
3667 }
3668
GetNumberFormat(SdrPowerPointImport const & rManager,SvxNumberFormat & rNumberFormat,sal_uInt32 nLevel,const PPTParaLevel & rParaLevel,const PPTCharLevel & rCharLevel,TSS_Type nInstance)3669 void PPTNumberFormatCreator::GetNumberFormat( SdrPowerPointImport const & rManager, SvxNumberFormat& rNumberFormat, sal_uInt32 nLevel, const PPTParaLevel& rParaLevel, const PPTCharLevel& rCharLevel, TSS_Type nInstance )
3670 {
3671 nIsBullet = ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BulletOn ) ) != 0 ? 1 : 0;
3672 nBulletChar = rParaLevel.mnBulletChar;
3673
3674 bool bBuHardFont;
3675 bBuHardFont = ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BuHardFont ) ) != 0;
3676 if ( bBuHardFont )
3677 nBulletFont = rParaLevel.mnBulletFont;
3678 else
3679 nBulletFont = rCharLevel.mnFont;
3680 nBulletHeight = rParaLevel.mnBulletHeight;
3681 nBulletColor = rParaLevel.mnBulletColor;
3682 nTextOfs = rParaLevel.mnTextOfs;
3683 nBulletOfs = rParaLevel.mnBulletOfs;
3684
3685 std::optional< sal_Int16 > oStartNumbering;
3686 ImplGetExtNumberFormat( rManager, rNumberFormat, nLevel, nInstance, TSS_Type::Unknown, oStartNumbering, rCharLevel.mnFontHeight, nullptr );
3687 if ( ( rNumberFormat.GetNumberingType() != SVX_NUM_BITMAP ) && ( nBulletHeight > 0x7fff ) )
3688 nBulletHeight = rCharLevel.mnFontHeight ? ((- static_cast<sal_Int16>(nBulletHeight)) * 100 ) / rCharLevel.mnFontHeight : 100;
3689 ImplGetNumberFormat( rManager, rNumberFormat );
3690 switch ( rNumberFormat.GetNumberingType() )
3691 {
3692 case SVX_NUM_CHARS_UPPER_LETTER :
3693 case SVX_NUM_CHARS_LOWER_LETTER :
3694 case SVX_NUM_ROMAN_UPPER :
3695 case SVX_NUM_ROMAN_LOWER :
3696 case SVX_NUM_ARABIC :
3697 case SVX_NUM_CHARS_UPPER_LETTER_N :
3698 case SVX_NUM_CHARS_LOWER_LETTER_N :
3699 {
3700 sal_uInt32 nFont = rCharLevel.mnFont;
3701 PptFontEntityAtom* pFontEnityAtom = rManager.GetFontEnityAtom( nFont );
3702 if ( pFontEnityAtom )
3703 {
3704 vcl::Font aFont;
3705 aFont.SetCharSet( pFontEnityAtom->eCharSet );
3706 aFont.SetFamilyName( pFontEnityAtom->aName );
3707 aFont.SetFamily( pFontEnityAtom->eFamily );
3708 aFont.SetPitch( pFontEnityAtom->ePitch );
3709 rNumberFormat.SetBulletFont( &aFont );
3710 }
3711 }
3712 break;
3713 default: break;
3714 }
3715 }
3716
GetNumberFormat(SdrPowerPointImport const & rManager,SvxNumberFormat & rNumberFormat,PPTParagraphObj * pParaObj,TSS_Type nDestinationInstance,std::optional<sal_Int16> & rStartNumbering)3717 bool PPTNumberFormatCreator::GetNumberFormat( SdrPowerPointImport const & rManager, SvxNumberFormat& rNumberFormat, PPTParagraphObj* pParaObj,
3718 TSS_Type nDestinationInstance, std::optional< sal_Int16 >& rStartNumbering )
3719 {
3720 sal_uInt32 nHardCount = 0;
3721 nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletOn, nIsBullet, nDestinationInstance ) ? 1 : 0;
3722 nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletChar, nBulletChar, nDestinationInstance ) ? 1 : 0;
3723 nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletFont, nBulletFont, nDestinationInstance ) ? 1 : 0;
3724 nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletHeight, nBulletHeight, nDestinationInstance ) ? 1 : 0;
3725 nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletColor, nBulletColor, nDestinationInstance ) ? 1 : 0;
3726 nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_TextOfs, nTextOfs, nDestinationInstance ) ? 1 : 0;
3727 nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletOfs, nBulletOfs, nDestinationInstance ) ? 1 : 0;
3728
3729 if ( nIsBullet )
3730 rNumberFormat.SetNumberingType( SVX_NUM_CHAR_SPECIAL );
3731
3732 sal_uInt32 nFontHeight = 24;
3733 PPTPortionObj* pPtr = pParaObj->First();
3734 if ( pPtr )
3735 pPtr->GetAttrib( PPT_CharAttr_FontHeight, nFontHeight, nDestinationInstance );
3736 if ( nIsBullet )
3737 nHardCount += ImplGetExtNumberFormat( rManager, rNumberFormat, pParaObj->mxParaSet->mnDepth,
3738 pParaObj->mnInstance, nDestinationInstance, rStartNumbering, nFontHeight, pParaObj ) ? 1 : 0;
3739
3740 if ( rNumberFormat.GetNumberingType() != SVX_NUM_BITMAP )
3741 pParaObj->UpdateBulletRelSize( nBulletHeight );
3742 if ( nHardCount )
3743 {
3744 ImplGetNumberFormat( rManager, rNumberFormat );
3745 switch ( rNumberFormat.GetNumberingType() )
3746 {
3747 case SVX_NUM_CHARS_UPPER_LETTER :
3748 case SVX_NUM_CHARS_LOWER_LETTER :
3749 case SVX_NUM_ROMAN_UPPER :
3750 case SVX_NUM_ROMAN_LOWER :
3751 case SVX_NUM_ARABIC :
3752 case SVX_NUM_CHARS_UPPER_LETTER_N :
3753 case SVX_NUM_CHARS_LOWER_LETTER_N :
3754 {
3755 if ( pPtr )
3756 {
3757 sal_uInt32 nFont;
3758 pPtr->GetAttrib( PPT_CharAttr_Font, nFont, nDestinationInstance );
3759 PptFontEntityAtom* pFontEnityAtom = rManager.GetFontEnityAtom( nFont );
3760 if ( pFontEnityAtom )
3761 {
3762 vcl::Font aFont;
3763 aFont.SetCharSet( pFontEnityAtom->eCharSet );
3764 aFont.SetFamilyName( pFontEnityAtom->aName );
3765 aFont.SetFamily( pFontEnityAtom->eFamily );
3766 aFont.SetPitch( pFontEnityAtom->ePitch );
3767 rNumberFormat.SetBulletFont( &aFont );
3768 }
3769 }
3770 }
3771 break;
3772 default: break;
3773 }
3774 }
3775 return nHardCount != 0;
3776 }
3777
ImplGetNumberFormat(SdrPowerPointImport const & rManager,SvxNumberFormat & rNumberFormat)3778 void PPTNumberFormatCreator::ImplGetNumberFormat( SdrPowerPointImport const & rManager, SvxNumberFormat& rNumberFormat )
3779 {
3780 vcl::Font aFont;
3781 PptFontEntityAtom* pAtom = rManager.GetFontEnityAtom( nBulletFont );
3782 if ( pAtom )
3783 {
3784 rtl_TextEncoding eCharSet( pAtom->eCharSet );
3785 aFont.SetFamilyName( pAtom->aName );
3786 aFont.SetCharSet( eCharSet );
3787 aFont.SetFamily( pAtom->eFamily );
3788 aFont.SetPitch( pAtom->ePitch );
3789 }
3790 Color aCol( rManager.MSO_TEXT_CLR_ToColor( nBulletColor ) );
3791 aFont.SetColor( aCol );
3792
3793 sal_uInt16 nBuChar = static_cast<sal_uInt16>(nBulletChar);
3794 if ( aFont.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
3795 {
3796 nBuChar &= 0x00ff;
3797 nBuChar |= 0xf000;
3798 }
3799 rNumberFormat.SetBulletFont( &aFont );
3800 rNumberFormat.SetBulletChar( nBuChar );
3801 rNumberFormat.SetBulletRelSize( static_cast<sal_uInt16>(nBulletHeight) );
3802 rNumberFormat.SetBulletColor( aCol );
3803 sal_uInt32 nAbsLSpace = convertMasterUnitToMm100(nTextOfs);
3804 sal_uInt32 nFirstLineOffset = nAbsLSpace - convertMasterUnitToMm100(nBulletOfs);
3805 rNumberFormat.SetAbsLSpace( nAbsLSpace );
3806 rNumberFormat.SetFirstLineOffset( -static_cast<sal_Int32>(nFirstLineOffset) );
3807 }
3808
PPTCharSheet(TSS_Type nInstance)3809 PPTCharSheet::PPTCharSheet( TSS_Type nInstance )
3810 {
3811 sal_uInt32 nColor = PPT_COLSCHEME_TEXT_UND_ZEILEN;
3812 sal_uInt16 nFontHeight(0);
3813 switch ( nInstance )
3814 {
3815 case TSS_Type::PageTitle :
3816 case TSS_Type::Title :
3817 {
3818 nColor = PPT_COLSCHEME_TITELTEXT;
3819 nFontHeight = 44;
3820 }
3821 break;
3822 case TSS_Type::Body :
3823 case TSS_Type::Subtitle :
3824 case TSS_Type::HalfBody :
3825 case TSS_Type::QuarterBody :
3826 nFontHeight = 32;
3827 break;
3828 case TSS_Type::Notes :
3829 nFontHeight = 12;
3830 break;
3831 case TSS_Type::Unused :
3832 case TSS_Type::TextInShape :
3833 nFontHeight = 24;
3834 break;
3835 default: break;
3836 }
3837 for (PPTCharLevel & nDepth : maCharLevel)
3838 {
3839 nDepth.mnFlags = 0;
3840 nDepth.mnFont = 0;
3841 nDepth.mnAsianOrComplexFont = 0xffff;
3842 nDepth.mnFontHeight = nFontHeight;
3843 nDepth.mnFontColor = nColor;
3844 nDepth.mnFontColorInStyleSheet = Color( static_cast<sal_uInt8>(nColor), static_cast<sal_uInt8>( nColor >> 8 ), static_cast<sal_uInt8>( nColor >> 16 ) );
3845 nDepth.mnEscapement = 0;
3846 }
3847 }
3848
Read(SvStream & rIn,sal_uInt32 nLevel)3849 void PPTCharSheet::Read( SvStream& rIn, sal_uInt32 nLevel)
3850 {
3851 // character attributes
3852 sal_uInt32 nCMask;
3853 sal_uInt16 nVal16;
3854 rIn.ReadUInt32( nCMask );
3855
3856 if ( nCMask & 0x0000FFFF )
3857 {
3858 sal_uInt16 nBitAttr;
3859 maCharLevel[ nLevel ].mnFlags &= ~static_cast<sal_uInt16>(nCMask);
3860 rIn.ReadUInt16( nBitAttr ); // Bit attributes (bold, underlined, ...)
3861 maCharLevel[ nLevel ].mnFlags |= nBitAttr;
3862 }
3863 if ( nCMask & ( 1 << PPT_CharAttr_Font ) ) // 0x00010000
3864 rIn.ReadUInt16( maCharLevel[ nLevel ].mnFont );
3865 if ( nCMask & ( 1 << PPT_CharAttr_AsianOrComplexFont ) ) // 0x00200000
3866 rIn.ReadUInt16( maCharLevel[ nLevel ].mnAsianOrComplexFont );
3867 if ( nCMask & ( 1 << PPT_CharAttr_ANSITypeface ) ) // 0x00400000
3868 rIn.ReadUInt16( nVal16 );
3869 if ( nCMask & ( 1 << PPT_CharAttr_Symbol ) ) // 0x00800000
3870 rIn.ReadUInt16( nVal16 );
3871 if ( nCMask & ( 1 << PPT_CharAttr_FontHeight ) ) // 0x00020000
3872 rIn.ReadUInt16( maCharLevel[ nLevel ].mnFontHeight );
3873 if ( nCMask & ( 1 << PPT_CharAttr_FontColor ) ) // 0x00040000
3874 {
3875 rIn.ReadUInt32( maCharLevel[ nLevel ].mnFontColor );
3876 if( ! (maCharLevel[ nLevel ].mnFontColor & 0xff000000 ) )
3877 maCharLevel[ nLevel ].mnFontColor = PPT_COLSCHEME_HINTERGRUND;
3878 }
3879 if ( nCMask & ( 1 << PPT_CharAttr_Escapement ) ) // 0x00080000
3880 rIn.ReadUInt16( maCharLevel[ nLevel ].mnEscapement );
3881 if ( nCMask & 0x00100000 ) // 0x00100000
3882 rIn.ReadUInt16( nVal16 );
3883
3884 nCMask >>= 24;
3885 while( nCMask )
3886 {
3887 if ( nCMask & 1 )
3888 {
3889 OSL_FAIL( "PPTCharSheet::Read - unknown attribute, send me this document (SJ)" );
3890 rIn.ReadUInt16( nVal16 );
3891 }
3892 nCMask >>= 1;
3893 }
3894 }
3895
PPTParaSheet(TSS_Type nInstance)3896 PPTParaSheet::PPTParaSheet( TSS_Type nInstance )
3897 {
3898 sal_uInt16 nBuFlags = 0;
3899 sal_uInt32 nBulletColor = 0x8000000;
3900 sal_uInt16 nUpperDist = 0;
3901
3902 switch ( nInstance )
3903 {
3904 case TSS_Type::PageTitle :
3905 case TSS_Type::Title :
3906 nBulletColor = PPT_COLSCHEME_TITELTEXT;
3907 break;
3908 case TSS_Type::Body :
3909 case TSS_Type::Subtitle :
3910 case TSS_Type::HalfBody :
3911 case TSS_Type::QuarterBody :
3912 {
3913 nBuFlags = 1;
3914 nUpperDist = 0x14;
3915 }
3916 break;
3917 case TSS_Type::Notes :
3918 nUpperDist = 0x1e;
3919 break;
3920 default: break;
3921 }
3922 for (PPTParaLevel & i : maParaLevel)
3923 {
3924 i.mnBuFlags = nBuFlags;
3925 i.mnBulletChar = 0x2022;
3926 i.mnBulletFont = 0;
3927 i.mnBulletHeight = 100;
3928 i.mnBulletColor = nBulletColor;
3929 i.mnAdjust = 0;
3930 i.mnLineFeed = 100;
3931 i.mnLowerDist = 0;
3932 i.mnUpperDist = nUpperDist;
3933 i.mnTextOfs = 0;
3934 i.mnBulletOfs = 0;
3935 i.mnDefaultTab = 0x240;
3936 i.mnAsianLineBreak = 0;
3937 i.mnBiDi = 0;
3938 }
3939 }
3940
Read(SdrPowerPointImport const & rManager,SvStream & rIn,sal_uInt32 nLevel,bool bFirst)3941 void PPTParaSheet::Read( SdrPowerPointImport const &
3942 #ifdef DBG_UTIL
3943 rManager
3944 #endif
3945 , SvStream& rIn
3946 , sal_uInt32 nLevel, bool bFirst )
3947 {
3948 // paragraph attributes
3949 sal_uInt16 nVal16, i, nMask16;
3950 sal_uInt32 nVal32, nPMask;
3951 rIn.ReadUInt32( nPMask );
3952
3953 nMask16 = static_cast<sal_uInt16>(nPMask) & 0xf;
3954 if ( nMask16 )
3955 {
3956 rIn.ReadUInt16( nVal16 );
3957 maParaLevel[ nLevel ].mnBuFlags &=~ nMask16;
3958 nVal16 &= nMask16;
3959 maParaLevel[ nLevel ].mnBuFlags |= nVal16;
3960 }
3961 if ( nPMask & 0x0080 )
3962 rIn.ReadUInt16( maParaLevel[ nLevel ].mnBulletChar );
3963 if ( nPMask & 0x0010 )
3964 rIn.ReadUInt16( maParaLevel[ nLevel ].mnBulletFont );
3965 if ( nPMask & 0x0040 )
3966 {
3967 rIn.ReadUInt16( nVal16 );
3968 maParaLevel[ nLevel ].mnBulletHeight = nVal16;
3969 }
3970 if ( nPMask & 0x0020 )
3971 {
3972 rIn.ReadUInt32( nVal32 );
3973 maParaLevel[ nLevel ].mnBulletColor = nVal32;
3974 }
3975 if ( bFirst )
3976 {
3977 if ( nPMask & 0xF00 )
3978 { // AbsJust!
3979 rIn.ReadUInt16( nVal16 );
3980 maParaLevel[ nLevel ].mnAdjust = nVal16 & 3;
3981 }
3982 if ( nPMask & 0x1000 )
3983 rIn.ReadUInt16( maParaLevel[ nLevel ].mnLineFeed );
3984 if ( nPMask & 0x2000 )
3985 rIn.ReadUInt16( maParaLevel[ nLevel ].mnUpperDist );
3986 if ( nPMask & 0x4000 )
3987 rIn.ReadUInt16( maParaLevel[ nLevel ].mnLowerDist );
3988 if ( nPMask & 0x8000 )
3989 rIn.ReadUInt16( maParaLevel[ nLevel ].mnTextOfs );
3990 if ( nPMask & 0x10000 )
3991 rIn.ReadUInt16( maParaLevel[ nLevel ].mnBulletOfs );
3992 if ( nPMask & 0x20000 )
3993 rIn.ReadUInt16( maParaLevel[ nLevel ].mnDefaultTab );
3994 if ( nPMask & 0x200000 )
3995 {
3996 // number of tabulators
3997 rIn.ReadUInt16( nVal16 );
3998 if (rIn.remainingSize() / sizeof(nVal32) < nVal16)
3999 return;
4000 for ( i = 0; i < nVal16; i++ )
4001 rIn.ReadUInt32( nVal32 ); // reading the tabulators
4002 }
4003 if ( nPMask & 0x40000 )
4004 rIn.ReadUInt16( nVal16 );
4005 if ( nPMask & 0x80000 )
4006 rIn.ReadUInt16( maParaLevel[ nLevel ].mnAsianLineBreak );
4007 if ( nPMask & 0x100000 )
4008 rIn.ReadUInt16( maParaLevel[ nLevel ].mnBiDi );
4009 }
4010 else
4011 {
4012 if ( nPMask & 0x800 )
4013 {
4014 rIn.ReadUInt16( nVal16 );
4015 maParaLevel[ nLevel ].mnAdjust = nVal16 & 3;
4016 }
4017 if ( nPMask & 0x1000 )
4018 rIn.ReadUInt16( maParaLevel[ nLevel ].mnLineFeed );
4019 if ( nPMask & 0x2000 )
4020 rIn.ReadUInt16( maParaLevel[ nLevel ].mnUpperDist );
4021 if ( nPMask & 0x4000 )
4022 rIn.ReadUInt16( maParaLevel[ nLevel ].mnLowerDist );
4023 if ( nPMask & 0x8000 )
4024 rIn.ReadUInt16( nVal16 );
4025 if ( nPMask & 0x100 )
4026 rIn.ReadUInt16( maParaLevel[ nLevel ].mnTextOfs );
4027 if ( nPMask & 0x200 )
4028 rIn.ReadUInt16( nVal16 );
4029 if ( nPMask & 0x400 )
4030 rIn.ReadUInt16( maParaLevel[ nLevel ].mnBulletOfs );
4031 if ( nPMask & 0x10000 )
4032 rIn.ReadUInt16( nVal16 );
4033 if ( nPMask & 0xe0000 )
4034 {
4035 sal_uInt16 nFlagsToModifyMask = static_cast<sal_uInt16>( ( nPMask >> 17 ) & 7 );
4036 rIn.ReadUInt16( nVal16 );
4037 // bits that are not involved to zero
4038 nVal16 &= nFlagsToModifyMask;
4039 // bits that are to change to zero
4040 maParaLevel[ nLevel ].mnAsianLineBreak &=~nFlagsToModifyMask;
4041 // now set the corresponding bits
4042 maParaLevel[ nLevel ].mnAsianLineBreak |= nVal16;
4043 }
4044 if ( nPMask & 0x100000 )
4045 {
4046 // number of tabulators
4047 rIn.ReadUInt16( nVal16 );
4048 for ( i = 0; i < nVal16; i++ )
4049 rIn.ReadUInt32( nVal32 ); // reading the tabulators
4050 }
4051 if ( nPMask & 0x200000 )
4052 rIn.ReadUInt16( maParaLevel[ nLevel ].mnBiDi );
4053 }
4054
4055 nPMask >>= 22;
4056 while( nPMask )
4057 {
4058 if ( nPMask & 1 )
4059 {
4060 #ifdef DBG_UTIL
4061 if (!(rManager.rImportParam.nImportFlags & PPT_IMPORTFLAGS_NO_TEXT_ASSERT))
4062 {
4063 OSL_FAIL( "PPTParaSheet::Read - unknown attribute, send me this document (SJ)" );
4064 }
4065 #endif
4066 rIn.ReadUInt16( nVal16 );
4067 }
4068 nPMask >>= 1;
4069 }
4070 }
4071
UpdateBulletRelSize(sal_uInt32 nLevel,sal_uInt16 nFontHeight)4072 void PPTParaSheet::UpdateBulletRelSize( sal_uInt32 nLevel, sal_uInt16 nFontHeight )
4073 {
4074 if ( maParaLevel[ nLevel ].mnBulletHeight > 0x7fff ) // a negative value is the absolute bullet height
4075 {
4076 sal_Int16 nBulletRelSize = static_cast<sal_Int16>(maParaLevel[ nLevel ].mnBulletHeight);
4077 nBulletRelSize = nFontHeight ? ((-nBulletRelSize) * 100 ) / nFontHeight : 100;
4078 if ( nBulletRelSize < 0 ) //bullet size over flow
4079 nBulletRelSize = 100;
4080 maParaLevel[ nLevel ].mnBulletHeight = nBulletRelSize;
4081 }
4082 }
4083
PPTStyleSheet(const DffRecordHeader & rSlideHd,SvStream & rIn,SdrPowerPointImport & rManager,const PPTTextParagraphStyleAtomInterpreter & rTxPFStyle,const PPTTextSpecInfo & rTextSpecInfo)4084 PPTStyleSheet::PPTStyleSheet( const DffRecordHeader& rSlideHd, SvStream& rIn, SdrPowerPointImport& rManager,
4085 const PPTTextParagraphStyleAtomInterpreter& rTxPFStyle,
4086 const PPTTextSpecInfo& rTextSpecInfo ) :
4087
4088 PPTNumberFormatCreator ( std::make_unique<PPTExtParaProv>( rManager, rIn, &rSlideHd ) ),
4089 maTxSI ( rTextSpecInfo )
4090 {
4091 sal_uInt32 nOldFilePos = rIn.Tell();
4092
4093 // default stylesheets
4094 mpCharSheet[ TSS_Type::PageTitle ] = std::make_unique<PPTCharSheet>( TSS_Type::PageTitle );
4095 mpCharSheet[ TSS_Type::Body ] = std::make_unique<PPTCharSheet>( TSS_Type::Body );
4096 mpCharSheet[ TSS_Type::Notes ] = std::make_unique<PPTCharSheet>( TSS_Type::Notes );
4097 mpCharSheet[ TSS_Type::Unused ] = std::make_unique<PPTCharSheet>( TSS_Type::Unused ); // this entry is not used by ppt
4098 mpCharSheet[ TSS_Type::TextInShape ] = std::make_unique<PPTCharSheet>( TSS_Type::TextInShape );
4099 mpParaSheet[ TSS_Type::PageTitle ] = std::make_unique<PPTParaSheet>( TSS_Type::PageTitle );
4100 mpParaSheet[ TSS_Type::Body ] = std::make_unique<PPTParaSheet>( TSS_Type::Body );
4101 mpParaSheet[ TSS_Type::Notes ] = std::make_unique<PPTParaSheet>( TSS_Type::Notes );
4102 mpParaSheet[ TSS_Type::Unused ] = std::make_unique<PPTParaSheet>( TSS_Type::Unused );
4103 mpParaSheet[ TSS_Type::TextInShape ] = std::make_unique<PPTParaSheet>( TSS_Type::TextInShape );
4104 // mpCharSheet[ TSS_Type::QuarterBody ], mpCharSheet[ TSS_Type::HalfBody ], mpCharSheet[ TSS_Type::Title ], mpCharSheet[ TSS_Type::Subtitle ] intentionally null
4105 // mpParaSheet[ TSS_Type::QuarterBody ], mpParaSheet[ TSS_Type::HalfBody ], mpParaSheet[ TSS_Type::Title ], mpParaSheet[ TSS_Type::Subtitle ] intentionally null
4106
4107 /* SJ: try to locate the txMasterStyleAtom in the Environment
4108
4109 it seems that the environment TextStyle is having a higher priority
4110 than the TextStyle that can be found within the master page
4111 */
4112 bool bFoundTxMasterStyleAtom04 = false;
4113 DffRecordHeader* pEnvHeader = rManager.aDocRecManager.GetRecordHeader( PPT_PST_Environment );
4114 if ( pEnvHeader )
4115 {
4116 pEnvHeader->SeekToContent( rIn );
4117 DffRecordHeader aTxMasterStyleHd;
4118 auto nEndRecPos = DffPropSet::SanitizeEndPos(rIn, pEnvHeader->GetRecEndFilePos());
4119 while (rIn.Tell() < nEndRecPos)
4120 {
4121 ReadDffRecordHeader( rIn, aTxMasterStyleHd );
4122 if ( aTxMasterStyleHd.nRecType == PPT_PST_TxMasterStyleAtom )
4123 {
4124 sal_uInt16 nLevelCnt(0);
4125 rIn.ReadUInt16(nLevelCnt);
4126
4127 sal_uInt16 nLev = 0;
4128 bool bFirst = true;
4129 bFoundTxMasterStyleAtom04 = true;
4130 auto nTxEndRecPos = DffPropSet::SanitizeEndPos(rIn, aTxMasterStyleHd.GetRecEndFilePos());
4131 while (rIn.GetError() == ERRCODE_NONE && rIn.Tell() < nTxEndRecPos && nLev < nLevelCnt && nLev < nMaxPPTLevels)
4132 {
4133 if ( nLev )
4134 {
4135 mpParaSheet[ TSS_Type::TextInShape ]->maParaLevel[ nLev ] = mpParaSheet[ TSS_Type::TextInShape ]->maParaLevel[ nLev - 1 ];
4136 mpCharSheet[ TSS_Type::TextInShape ]->maCharLevel[ nLev ] = mpCharSheet[ TSS_Type::TextInShape ]->maCharLevel[ nLev - 1 ];
4137 }
4138 mpParaSheet[ TSS_Type::TextInShape ]->Read( rManager, rIn, nLev, bFirst );
4139 if ( !nLev )
4140 {
4141 // set paragraph defaults for instance 4 (TSS_Type::TextInShape)
4142 if ( rTxPFStyle.bValid )
4143 {
4144 PPTParaLevel& rParaLevel = mpParaSheet[ TSS_Type::TextInShape ]->maParaLevel[ 0 ];
4145 rParaLevel.mnAsianLineBreak = 0;
4146 if ( rTxPFStyle.bForbiddenRules )
4147 rParaLevel.mnAsianLineBreak |= 1;
4148 if ( !rTxPFStyle.bLatinTextWrap )
4149 rParaLevel.mnAsianLineBreak |= 2;
4150 if ( rTxPFStyle.bHangingPunctuation )
4151 rParaLevel.mnAsianLineBreak |= 4;
4152 }
4153 }
4154 mpCharSheet[ TSS_Type::TextInShape ]->Read( rIn, nLev );
4155 mpParaSheet[ TSS_Type::TextInShape ]->UpdateBulletRelSize( nLev, mpCharSheet[ TSS_Type::TextInShape ]->maCharLevel[ nLev ].mnFontHeight );
4156 bFirst = false;
4157 nLev++;
4158 }
4159 break;
4160 }
4161 else
4162 {
4163 if (!aTxMasterStyleHd.SeekToEndOfRecord(rIn))
4164 break;
4165 }
4166 }
4167 }
4168
4169 rSlideHd.SeekToContent( rIn );
4170
4171 DffRecordHeader aTxMasterStyleHd;
4172 auto nEndRecPos = DffPropSet::SanitizeEndPos(rIn, rSlideHd.GetRecEndFilePos());
4173 while (rIn.Tell() < nEndRecPos)
4174 {
4175 ReadDffRecordHeader( rIn, aTxMasterStyleHd );
4176 if ( aTxMasterStyleHd.nRecType == PPT_PST_TxMasterStyleAtom )
4177 break;
4178 else
4179 {
4180 if (!aTxMasterStyleHd.SeekToEndOfRecord(rIn))
4181 break;
4182 }
4183 }
4184 while ( ( aTxMasterStyleHd.nRecType == PPT_PST_TxMasterStyleAtom ) && ( rIn.Tell() < nEndRecPos ) ) //TODO: aTxMasterStyleHd may be used without having been properly initialized
4185 {
4186 TSS_Type nInstance = static_cast<TSS_Type>(aTxMasterStyleHd.nRecInstance);
4187 if ( ( nInstance <= TSS_Type::LAST ) &&
4188 ( ( nInstance != TSS_Type::TextInShape ) || !bFoundTxMasterStyleAtom04 ) )
4189 {
4190 if ( nInstance > TSS_Type::TextInShape )
4191 {
4192 mpCharSheet[ nInstance ].reset(); // be sure to delete the old one if this instance comes twice
4193 mpParaSheet[ nInstance ].reset();
4194
4195 switch ( nInstance )
4196 {
4197 case TSS_Type::Subtitle :
4198 {
4199 mpCharSheet[ TSS_Type::Subtitle ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::Body ] ) );
4200 mpParaSheet[ TSS_Type::Subtitle ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::Body ] ) );
4201 }
4202 break;
4203 case TSS_Type::Title :
4204 {
4205 mpCharSheet[ TSS_Type::Title ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::PageTitle ] ) );
4206 mpParaSheet[ TSS_Type::Title ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::PageTitle ] ) );
4207 }
4208 break;
4209 case TSS_Type::HalfBody :
4210 {
4211 mpCharSheet[ TSS_Type::HalfBody ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::Body ] ) );
4212 mpParaSheet[ TSS_Type::HalfBody ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::Body ] ) );
4213 }
4214 break;
4215
4216 case TSS_Type::QuarterBody :
4217 {
4218 mpCharSheet[ TSS_Type::QuarterBody ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::Body ] ) );
4219 mpParaSheet[ TSS_Type::QuarterBody ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::Body ] ) );
4220 }
4221 break;
4222 default: break;
4223 }
4224 }
4225 sal_uInt16 nLevelCnt(0);
4226 rIn.ReadUInt16(nLevelCnt);
4227 if (nLevelCnt > nMaxPPTLevels)
4228 {
4229 OSL_FAIL( "PPTStyleSheet::Ppt-TextStylesheet has more than 5 levels! (SJ)" );
4230 nLevelCnt = nMaxPPTLevels;
4231 }
4232 sal_uInt16 nLev = 0;
4233 bool bFirst = true;
4234
4235 auto nTxEndRecPos = DffPropSet::SanitizeEndPos(rIn, aTxMasterStyleHd.GetRecEndFilePos());
4236 while ( rIn.GetError() == ERRCODE_NONE && rIn.Tell() < nTxEndRecPos && nLev < nLevelCnt )
4237 {
4238 if ( nLev && ( nInstance < TSS_Type::Subtitle ) )
4239 {
4240 mpParaSheet[ nInstance ]->maParaLevel[ nLev ] = mpParaSheet[ nInstance ]->maParaLevel[ nLev - 1 ];
4241 mpCharSheet[ nInstance ]->maCharLevel[ nLev ] = mpCharSheet[ nInstance ]->maCharLevel[ nLev - 1 ];
4242 }
4243
4244 // Exception: Template 5, 6 (MasterTitle Title and SubTitle)
4245 if ( nInstance >= TSS_Type::Subtitle )
4246 {
4247 bFirst = false;
4248
4249 sal_uInt16 nDontKnow;
4250 rIn.ReadUInt16( nDontKnow );
4251 }
4252 mpParaSheet[ nInstance ]->Read( rManager, rIn, nLev, bFirst );
4253 mpCharSheet[ nInstance ]->Read( rIn, nLev );
4254 mpParaSheet[ nInstance ]->UpdateBulletRelSize( nLev, mpCharSheet[ nInstance ]->maCharLevel[ nLev ].mnFontHeight );
4255 bFirst = false;
4256 nLev++;
4257 }
4258 #ifdef DBG_UTIL
4259 if (!(rManager.rImportParam.nImportFlags & PPT_IMPORTFLAGS_NO_TEXT_ASSERT))
4260 {
4261 if ( rIn.GetError() == ERRCODE_NONE )
4262 {
4263 OStringBuffer aMsg;
4264 if ( rIn.Tell() > aTxMasterStyleHd.GetRecEndFilePos() )
4265 {
4266 aMsg.append("\n reading too many bytes:" +
4267 OString::number(rIn.Tell() - aTxMasterStyleHd.GetRecEndFilePos()));
4268 }
4269 if ( rIn.Tell() < aTxMasterStyleHd.GetRecEndFilePos() )
4270 {
4271 aMsg.append("\n reading too few bytes:" +
4272 OString::number(aTxMasterStyleHd.GetRecEndFilePos() - rIn.Tell()));
4273 }
4274 if (aMsg.getLength())
4275 {
4276 aMsg.insert(0, "PptStyleSheet::operator>>[]");
4277 OSL_FAIL(aMsg.getStr());
4278 }
4279 }
4280 if ( rIn.Tell() != aTxMasterStyleHd.GetRecEndFilePos() )
4281 SAL_WARN( "filter.ms", "SJ: Wrong number of bytes read during import of PPT style");
4282 }
4283 #endif
4284 }
4285 if (!aTxMasterStyleHd.SeekToEndOfRecord(rIn))
4286 break;
4287 ReadDffRecordHeader( rIn, aTxMasterStyleHd );
4288 }
4289 if ( !mpCharSheet[ TSS_Type::Subtitle ] )
4290 {
4291 mpCharSheet[ TSS_Type::Subtitle ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::Body ] ) );
4292 mpParaSheet[ TSS_Type::Subtitle ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::Body ] ) );
4293 }
4294 if ( !mpCharSheet[ TSS_Type::Title ] )
4295 {
4296 mpCharSheet[ TSS_Type::Title ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::PageTitle ] ) );
4297 mpParaSheet[ TSS_Type::Title ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::PageTitle ] ) );
4298 }
4299 if ( !mpCharSheet[ TSS_Type::HalfBody ] )
4300 {
4301 mpCharSheet[ TSS_Type::HalfBody ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::Body ] ) );
4302 mpParaSheet[ TSS_Type::HalfBody ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::Body ] ) );
4303 }
4304 if ( !mpCharSheet[ TSS_Type::QuarterBody ] )
4305 {
4306 mpCharSheet[ TSS_Type::QuarterBody ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::Body ] ) );
4307 mpParaSheet[ TSS_Type::QuarterBody ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::Body ] ) );
4308 }
4309 if ( !bFoundTxMasterStyleAtom04 )
4310 { // try to locate the txMasterStyleAtom in the Environment
4311 DffRecordHeader* pEnvHeader2 = rManager.aDocRecManager.GetRecordHeader( PPT_PST_Environment );
4312 if ( pEnvHeader2 )
4313 {
4314 pEnvHeader2->SeekToContent( rIn );
4315 DffRecordHeader aTxMasterStyleHd2;
4316 auto nEnvEndRecPos = DffPropSet::SanitizeEndPos(rIn, pEnvHeader2->GetRecEndFilePos());
4317 while (rIn.Tell() < nEnvEndRecPos)
4318 {
4319 ReadDffRecordHeader( rIn, aTxMasterStyleHd2 );
4320 if ( aTxMasterStyleHd2.nRecType == PPT_PST_TxMasterStyleAtom )
4321 {
4322 sal_uInt16 nLevelCnt;
4323 rIn.ReadUInt16( nLevelCnt );
4324
4325 sal_uInt16 nLev = 0;
4326 bool bFirst = true;
4327 auto nTxEndRecPos = DffPropSet::SanitizeEndPos(rIn, aTxMasterStyleHd2.GetRecEndFilePos());
4328 while ( rIn.GetError() == ERRCODE_NONE && rIn.Tell() < nTxEndRecPos && nLev < nLevelCnt )
4329 {
4330 if ( nLev )
4331 {
4332 mpParaSheet[ TSS_Type::TextInShape ]->maParaLevel[ nLev ] = mpParaSheet[ TSS_Type::TextInShape ]->maParaLevel[ nLev - 1 ];
4333 mpCharSheet[ TSS_Type::TextInShape ]->maCharLevel[ nLev ] = mpCharSheet[ TSS_Type::TextInShape ]->maCharLevel[ nLev - 1 ];
4334 }
4335 mpParaSheet[ TSS_Type::TextInShape ]->Read( rManager, rIn, nLev, bFirst );
4336 if ( !nLev )
4337 {
4338 // set paragraph defaults for instance 4 (TSS_Type::TextInShape)
4339 if ( rTxPFStyle.bValid )
4340 {
4341 PPTParaLevel& rParaLevel = mpParaSheet[ TSS_Type::TextInShape ]->maParaLevel[ 0 ];
4342 rParaLevel.mnAsianLineBreak = 0;
4343 if ( rTxPFStyle.bForbiddenRules )
4344 rParaLevel.mnAsianLineBreak |= 1;
4345 if ( !rTxPFStyle.bLatinTextWrap )
4346 rParaLevel.mnAsianLineBreak |= 2;
4347 if ( rTxPFStyle.bHangingPunctuation )
4348 rParaLevel.mnAsianLineBreak |= 4;
4349 }
4350 }
4351 mpCharSheet[ TSS_Type::TextInShape ]->Read( rIn, nLev );
4352 mpParaSheet[ TSS_Type::TextInShape ]->UpdateBulletRelSize( nLev, mpCharSheet[ TSS_Type::TextInShape ]->maCharLevel[ nLev ].mnFontHeight );
4353 bFirst = false;
4354 nLev++;
4355 }
4356 break;
4357 }
4358 else
4359 {
4360 if (!aTxMasterStyleHd2.SeekToEndOfRecord(rIn))
4361 break;
4362 }
4363 }
4364 }
4365 }
4366 rIn.Seek( nOldFilePos );
4367
4368 // will create the default numbulletitem for each instance
4369 for ( auto i : o3tl::enumrange<TSS_Type>() )
4370 {
4371 sal_uInt16 nLevels, nDepth = 0;
4372 SvxNumRuleType eNumRuleType;
4373
4374 switch ( i )
4375 {
4376 case TSS_Type::PageTitle :
4377 case TSS_Type::Title :
4378 nLevels = 1;
4379 eNumRuleType = SvxNumRuleType::NUMBERING;
4380 break;
4381 case TSS_Type::Subtitle :
4382 nLevels = SVX_MAX_NUM;
4383 eNumRuleType = SvxNumRuleType::NUMBERING;
4384 break;
4385 case TSS_Type::Body :
4386 case TSS_Type::HalfBody :
4387 case TSS_Type::QuarterBody :
4388 nLevels = SVX_MAX_NUM;
4389 eNumRuleType = SvxNumRuleType::PRESENTATION_NUMBERING;
4390 break;
4391 default :
4392 case TSS_Type::Notes :
4393 case TSS_Type::Unused :
4394 case TSS_Type::TextInShape :
4395 nLevels = SVX_MAX_NUM;
4396 eNumRuleType = SvxNumRuleType::NUMBERING;
4397 break;
4398 }
4399 SvxNumRule aRule( SvxNumRuleFlags::BULLET_REL_SIZE | SvxNumRuleFlags::BULLET_COLOR,
4400 nLevels, false, eNumRuleType );
4401 for ( sal_uInt16 nCount = 0; nDepth < nLevels; nCount++ )
4402 {
4403 const PPTParaLevel& rParaLevel = mpParaSheet[ i ]->maParaLevel[ nCount ];
4404 const PPTCharLevel& rCharLevel = mpCharSheet[ i ]->maCharLevel[ nCount ];
4405 SvxNumberFormat aNumberFormat( SVX_NUM_CHAR_SPECIAL );
4406 aNumberFormat.SetBulletChar( ' ' );
4407 GetNumberFormat( rManager, aNumberFormat, nCount, rParaLevel, rCharLevel, i );
4408 aRule.SetLevel( nDepth++, aNumberFormat );
4409 if ( nCount >= 4 )
4410 {
4411 for ( ;nDepth < nLevels; nDepth++ )
4412 aRule.SetLevel( nDepth, aNumberFormat );
4413 }
4414 }
4415 mpNumBulletItem[ i ] = std::make_unique<SvxNumBulletItem>( aRule, EE_PARA_NUMBULLET );
4416 }
4417 }
4418
~PPTStyleSheet()4419 PPTStyleSheet::~PPTStyleSheet()
4420 {
4421 for ( auto i : o3tl::enumrange<TSS_Type>() )
4422 {
4423 mpCharSheet[i].reset();
4424 mpParaSheet[i].reset();
4425 mpNumBulletItem[i].reset();
4426 }
4427 }
4428
PPTParaPropSet()4429 PPTParaPropSet::PPTParaPropSet()
4430 : mnOriginalTextPos(0)
4431 , mxParaSet( new ImplPPTParaPropSet )
4432 {
4433 mxParaSet->mnHasAnm = 1;
4434 }
4435
PPTParaPropSet(PPTParaPropSet const & rParaPropSet)4436 PPTParaPropSet::PPTParaPropSet( PPTParaPropSet const & rParaPropSet )
4437 {
4438 mxParaSet = rParaPropSet.mxParaSet;
4439 mnOriginalTextPos = rParaPropSet.mnOriginalTextPos;
4440 }
4441
~PPTParaPropSet()4442 PPTParaPropSet::~PPTParaPropSet()
4443 {
4444 }
4445
operator =(const PPTParaPropSet & rParaPropSet)4446 PPTParaPropSet& PPTParaPropSet::operator=( const PPTParaPropSet& rParaPropSet )
4447 {
4448 if ( this != &rParaPropSet )
4449 {
4450 mxParaSet = rParaPropSet.mxParaSet;
4451 mnOriginalTextPos = rParaPropSet.mnOriginalTextPos;
4452 }
4453 return *this;
4454 }
4455
PPTCharPropSet(sal_uInt32 nParagraph)4456 PPTCharPropSet::PPTCharPropSet(sal_uInt32 nParagraph)
4457 : mnOriginalTextPos(0)
4458 , mnParagraph(nParagraph)
4459 , mpImplPPTCharPropSet()
4460 {
4461 mnHylinkOrigColor = 0;
4462 mbIsHyperlink = false;
4463 mbHardHylinkOrigColor = false;
4464 mnLanguage[ 0 ] = mnLanguage[ 1 ] = mnLanguage[ 2 ] = LANGUAGE_SYSTEM;
4465 }
4466
PPTCharPropSet(const PPTCharPropSet & rCharPropSet)4467 PPTCharPropSet::PPTCharPropSet( const PPTCharPropSet& rCharPropSet )
4468 : mpImplPPTCharPropSet( rCharPropSet.mpImplPPTCharPropSet )
4469 {
4470 mnHylinkOrigColor = rCharPropSet.mnHylinkOrigColor;
4471 mbIsHyperlink = rCharPropSet.mbIsHyperlink;
4472 mbHardHylinkOrigColor = rCharPropSet.mbHardHylinkOrigColor;
4473
4474 mnParagraph = rCharPropSet.mnParagraph;
4475 mnOriginalTextPos = rCharPropSet.mnOriginalTextPos;
4476 maString = rCharPropSet.maString;
4477 mpFieldItem.reset( rCharPropSet.mpFieldItem ? new SvxFieldItem( *rCharPropSet.mpFieldItem ) : nullptr );
4478 mnLanguage[ 0 ] = rCharPropSet.mnLanguage[ 0 ];
4479 mnLanguage[ 1 ] = rCharPropSet.mnLanguage[ 1 ];
4480 mnLanguage[ 2 ] = rCharPropSet.mnLanguage[ 2 ];
4481 }
4482
PPTCharPropSet(const PPTCharPropSet & rCharPropSet,sal_uInt32 nParagraph)4483 PPTCharPropSet::PPTCharPropSet( const PPTCharPropSet& rCharPropSet, sal_uInt32 nParagraph )
4484 : mpImplPPTCharPropSet(rCharPropSet.mpImplPPTCharPropSet)
4485 {
4486 mnHylinkOrigColor = rCharPropSet.mnHylinkOrigColor;
4487 mbIsHyperlink = rCharPropSet.mbIsHyperlink;
4488 mbHardHylinkOrigColor = rCharPropSet.mbHardHylinkOrigColor;
4489
4490 mnParagraph = nParagraph;
4491 mnOriginalTextPos = rCharPropSet.mnOriginalTextPos;
4492 maString = rCharPropSet.maString;
4493 mpFieldItem.reset( rCharPropSet.mpFieldItem ? new SvxFieldItem( *rCharPropSet.mpFieldItem ) : nullptr );
4494 mnLanguage[ 0 ] = mnLanguage[ 1 ] = mnLanguage[ 2 ] = LANGUAGE_SYSTEM;
4495 }
4496
~PPTCharPropSet()4497 PPTCharPropSet::~PPTCharPropSet()
4498 {
4499 }
4500
operator =(const PPTCharPropSet & rCharPropSet)4501 PPTCharPropSet& PPTCharPropSet::operator=( const PPTCharPropSet& rCharPropSet )
4502 {
4503 if ( this != &rCharPropSet )
4504 {
4505 mpImplPPTCharPropSet = rCharPropSet.mpImplPPTCharPropSet;
4506 mnOriginalTextPos = rCharPropSet.mnOriginalTextPos;
4507 mnParagraph = rCharPropSet.mnParagraph;
4508 maString = rCharPropSet.maString;
4509 mpFieldItem.reset( rCharPropSet.mpFieldItem ? new SvxFieldItem( *rCharPropSet.mpFieldItem ) : nullptr );
4510 }
4511 return *this;
4512 }
4513
SetFont(sal_uInt16 nFont)4514 void PPTCharPropSet::SetFont( sal_uInt16 nFont )
4515 {
4516 sal_uInt32 nMask = 1 << PPT_CharAttr_Font;
4517 bool bDoNotMake = (mpImplPPTCharPropSet->mnAttrSet & nMask) != 0;
4518
4519 if ( bDoNotMake )
4520 bDoNotMake = nFont == mpImplPPTCharPropSet->mnFont;
4521
4522 if ( !bDoNotMake )
4523 {
4524 mpImplPPTCharPropSet->mnFont = nFont;
4525 mpImplPPTCharPropSet->mnAttrSet |= nMask;
4526 }
4527 }
4528
SetColor(sal_uInt32 nColor)4529 void PPTCharPropSet::SetColor( sal_uInt32 nColor )
4530 {
4531 mpImplPPTCharPropSet->mnColor = nColor;
4532 mpImplPPTCharPropSet->mnAttrSet |= 1 << PPT_CharAttr_FontColor;
4533 }
4534
PPTRuler()4535 PPTRuler::PPTRuler()
4536 : nFlags(0)
4537 , nDefaultTab(0x240)
4538 , nTabCount(0)
4539 {
4540 }
4541
~PPTRuler()4542 PPTRuler::~PPTRuler()
4543 {
4544 };
4545
4546
PPTTextRulerInterpreter()4547 PPTTextRulerInterpreter::PPTTextRulerInterpreter() :
4548 mxImplRuler ( new PPTRuler() )
4549 {
4550 }
4551
PPTTextRulerInterpreter(PPTTextRulerInterpreter const & rRuler)4552 PPTTextRulerInterpreter::PPTTextRulerInterpreter( PPTTextRulerInterpreter const & rRuler )
4553 {
4554 mxImplRuler = rRuler.mxImplRuler;
4555 }
4556
PPTTextRulerInterpreter(sal_uInt32 nFileOfs,DffRecordHeader const & rHeader,SvStream & rIn)4557 PPTTextRulerInterpreter::PPTTextRulerInterpreter( sal_uInt32 nFileOfs, DffRecordHeader const & rHeader, SvStream& rIn ) :
4558 mxImplRuler ( new PPTRuler() )
4559 {
4560 if ( nFileOfs == 0xffffffff )
4561 return;
4562
4563 sal_uInt32 nOldPos = rIn.Tell();
4564 DffRecordHeader rHd;
4565 if ( nFileOfs )
4566 {
4567 rIn.Seek( nFileOfs );
4568 ReadDffRecordHeader( rIn, rHd );
4569 }
4570 else
4571 {
4572 rHeader.SeekToContent( rIn );
4573 if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_TextRulerAtom, rHeader.GetRecEndFilePos(), &rHd ) )
4574 nFileOfs++;
4575 }
4576 if ( nFileOfs )
4577 {
4578 bool bRecordOk = true;
4579
4580 sal_Int16 nTCount(0);
4581 sal_Int32 i;
4582 rIn.ReadInt32( mxImplRuler->nFlags );
4583
4584 // number of indent levels, unused now
4585 if ( mxImplRuler->nFlags & 2 )
4586 rIn.ReadInt16( nTCount );
4587 if ( mxImplRuler->nFlags & 1 )
4588 rIn.ReadUInt16( mxImplRuler->nDefaultTab );
4589 if ( mxImplRuler->nFlags & 4 )
4590 {
4591 rIn.ReadInt16(nTCount);
4592
4593 const size_t nMaxPossibleRecords = rIn.remainingSize() / (2*sizeof(sal_uInt16));
4594 const sal_uInt16 nTabCount(nTCount);
4595
4596 bRecordOk = nTabCount <= nMaxPossibleRecords;
4597
4598 if (nTCount && bRecordOk)
4599 {
4600 mxImplRuler->nTabCount = nTabCount;
4601 mxImplRuler->pTab.reset( new PPTTabEntry[ mxImplRuler->nTabCount ] );
4602 for ( i = 0; i < nTCount; i++ )
4603 {
4604 rIn.ReadUInt16( mxImplRuler->pTab[ i ].nOffset )
4605 .ReadUInt16( mxImplRuler->pTab[ i ].nStyle );
4606 }
4607 }
4608 }
4609
4610 if (bRecordOk)
4611 {
4612 for ( i = 0; i < 5; i++ )
4613 {
4614 if ( mxImplRuler->nFlags & ( 8 << i ) )
4615 rIn.ReadUInt16( mxImplRuler->nTextOfs[ i ] );
4616 if ( mxImplRuler->nFlags & ( 256 << i ) )
4617 rIn.ReadUInt16( mxImplRuler->nBulletOfs[ i ] );
4618 if( mxImplRuler->nBulletOfs[ i ] > 0x7fff)
4619 {
4620 // workaround
4621 // when bullet offset is > 0x7fff, the paragraph should look like
4622 // * first line text
4623 // second line text
4624
4625 // we add to bullet para indent 0xffff - bullet offset. It looks like
4626 // best we can do for now
4627 mxImplRuler->nTextOfs[ i ] += 0xffff - mxImplRuler->nBulletOfs[ i ];
4628 mxImplRuler->nBulletOfs[ i ] = 0;
4629 }
4630 }
4631 }
4632 }
4633 rIn.Seek( nOldPos );
4634 }
4635
GetDefaultTab(sal_uInt16 & nValue) const4636 bool PPTTextRulerInterpreter::GetDefaultTab( sal_uInt16& nValue ) const
4637 {
4638 if ( ! ( mxImplRuler->nFlags & 1 ) )
4639 return false;
4640 nValue = mxImplRuler->nDefaultTab;
4641 return true;
4642 }
4643
GetTextOfs(sal_uInt32 nLevel,sal_uInt16 & nValue) const4644 bool PPTTextRulerInterpreter::GetTextOfs( sal_uInt32 nLevel, sal_uInt16& nValue ) const
4645 {
4646 if ( ! ( ( nLevel < 5 ) && ( mxImplRuler->nFlags & ( 8 << nLevel ) ) ) )
4647 return false;
4648 nValue = mxImplRuler->nTextOfs[ nLevel ];
4649 return true;
4650 }
4651
GetBulletOfs(sal_uInt32 nLevel,sal_uInt16 & nValue) const4652 bool PPTTextRulerInterpreter::GetBulletOfs( sal_uInt32 nLevel, sal_uInt16& nValue ) const
4653 {
4654 if ( ! ( ( nLevel < 5 ) && ( mxImplRuler->nFlags & ( 256 << nLevel ) ) ) )
4655 return false;
4656 nValue = mxImplRuler->nBulletOfs[ nLevel ];
4657 return true;
4658 }
4659
operator =(PPTTextRulerInterpreter & rRuler)4660 PPTTextRulerInterpreter& PPTTextRulerInterpreter::operator=( PPTTextRulerInterpreter& rRuler )
4661 {
4662 if ( this != &rRuler )
4663 {
4664 mxImplRuler = rRuler.mxImplRuler;
4665 }
4666 return *this;
4667 }
4668
~PPTTextRulerInterpreter()4669 PPTTextRulerInterpreter::~PPTTextRulerInterpreter()
4670 {
4671 }
4672
PPTTextParagraphStyleAtomInterpreter()4673 PPTTextParagraphStyleAtomInterpreter::PPTTextParagraphStyleAtomInterpreter() :
4674 bValid ( false ),
4675 bForbiddenRules ( false ),
4676 bHangingPunctuation ( false ),
4677 bLatinTextWrap ( false )
4678 {
4679 }
4680
Read(SvStream & rIn,const DffRecordHeader & rRecHd)4681 bool PPTTextParagraphStyleAtomInterpreter::Read( SvStream& rIn, const DffRecordHeader& rRecHd )
4682 {
4683 bValid = false;
4684 rRecHd.SeekToContent( rIn );
4685 sal_uInt32 nDummy32, nFlags, nRecEndPos = rRecHd.GetRecEndFilePos();
4686 sal_uInt16 nDummy16;
4687
4688 rIn.ReadUInt16( nDummy16 )
4689 .ReadUInt32( nFlags );
4690
4691 if ( nFlags & 0xf && ( rIn.Tell() < nRecEndPos ) )
4692 rIn.ReadUInt16( nDummy16 ); // BuFlags
4693 if ( nFlags & 0x80 && ( rIn.Tell() < nRecEndPos ) )
4694 rIn.ReadUInt16( nDummy16 ); // BuChar
4695 if ( nFlags & 0x10 && ( rIn.Tell() < nRecEndPos ) )
4696 rIn.ReadUInt16( nDummy16 ); // nBuFont;
4697 if ( nFlags & 0x40 && ( rIn.Tell() < nRecEndPos ) )
4698 rIn.ReadUInt16( nDummy16 ); // nBuHeight;
4699 if ( nFlags & 0x0020 && ( rIn.Tell() < nRecEndPos ) )
4700 rIn.ReadUInt32( nDummy32 ); // nBuColor;
4701 if ( nFlags & 0x800 && ( rIn.Tell() < nRecEndPos ) )
4702 rIn.ReadUInt16( nDummy16 ); // AbsJust!
4703 if ( nFlags & 0x400 && ( rIn.Tell() < nRecEndPos ) )
4704 rIn.ReadUInt16( nDummy16 );
4705 if ( nFlags & 0x200 && ( rIn.Tell() < nRecEndPos ) )
4706 rIn.ReadUInt16( nDummy16 );
4707 if ( nFlags & 0x100 && ( rIn.Tell() < nRecEndPos ) )
4708 rIn.ReadUInt16( nDummy16 );
4709 if ( nFlags & 0x1000 && ( rIn.Tell() < nRecEndPos ) )
4710 rIn.ReadUInt16( nDummy16 ); // LineFeed
4711 if ( nFlags & 0x2000 && ( rIn.Tell() < nRecEndPos ) )
4712 rIn.ReadUInt16( nDummy16 ); // nUpperDist
4713 if ( nFlags & 0x4000 && ( rIn.Tell() < nRecEndPos ) )
4714 rIn.ReadUInt16( nDummy16 ); // nLowerDist
4715 if ( nFlags & 0x8000 && ( rIn.Tell() < nRecEndPos ) )
4716 rIn.ReadUInt16( nDummy16 );
4717 if ( nFlags & 0x10000 && ( rIn.Tell() < nRecEndPos ) )
4718 rIn.ReadUInt16( nDummy16 );
4719 if ( nFlags & 0xe0000 && ( rIn.Tell() < nRecEndPos ) )
4720 {
4721 rIn.ReadUInt16( nDummy16 );
4722 if ( nFlags & 0x20000 )
4723 bForbiddenRules = ( nDummy16 & 1 ) == 1;
4724 if ( nFlags & 0x40000 )
4725 bLatinTextWrap = ( nDummy16 & 2 ) == 0;
4726 if ( nFlags & 0x80000 )
4727 bHangingPunctuation = ( nDummy16 & 4 ) == 4;
4728 }
4729 nFlags &=~ 0xfffff;
4730 sal_uInt32 nMask = 0x100000;
4731 while ( nFlags && nMask && ( rIn.Tell() < nRecEndPos ) )
4732 {
4733 if ( nFlags & nMask )
4734 {
4735 rIn.ReadUInt16( nDummy16 );
4736 nFlags ^= nMask;
4737 }
4738 nMask <<= 1;
4739 }
4740 bValid = rIn.Tell() == nRecEndPos;
4741 return bValid;
4742 }
4743
~PPTTextParagraphStyleAtomInterpreter()4744 PPTTextParagraphStyleAtomInterpreter::~PPTTextParagraphStyleAtomInterpreter()
4745 {
4746
4747 }
4748
PPTTextSpecInfo(sal_uInt32 _nCharIdx)4749 PPTTextSpecInfo::PPTTextSpecInfo( sal_uInt32 _nCharIdx ) :
4750 nCharIdx ( _nCharIdx ),
4751 nDontKnow ( 1 )
4752 {
4753 nLanguage[ 0 ] = LANGUAGE_PROCESS_OR_USER_DEFAULT;
4754 nLanguage[ 1 ] = LANGUAGE_SYSTEM;
4755 nLanguage[ 2 ] = LANGUAGE_SYSTEM;
4756 }
4757
PPTTextSpecInfoAtomInterpreter()4758 PPTTextSpecInfoAtomInterpreter::PPTTextSpecInfoAtomInterpreter() :
4759 bValid ( false )
4760 {
4761 }
4762
Read(SvStream & rIn,const DffRecordHeader & rRecHd,sal_uInt16 nRecordType,const PPTTextSpecInfo * pTextSpecDefault)4763 bool PPTTextSpecInfoAtomInterpreter::Read( SvStream& rIn, const DffRecordHeader& rRecHd,
4764 sal_uInt16 nRecordType, const PPTTextSpecInfo* pTextSpecDefault )
4765 {
4766 bValid = false;
4767 sal_uInt32 nCharIdx = 0;
4768 rRecHd.SeekToContent( rIn );
4769
4770 auto nEndRecPos = DffPropSet::SanitizeEndPos(rIn, rRecHd.GetRecEndFilePos());
4771 while (rIn.Tell() < nEndRecPos && rIn.good())
4772 {
4773 if ( nRecordType == PPT_PST_TextSpecInfoAtom )
4774 {
4775 sal_uInt32 nCharCount(0);
4776 rIn.ReadUInt32( nCharCount );
4777 nCharIdx += nCharCount;
4778 }
4779
4780 sal_uInt32 nFlags(0);
4781 rIn.ReadUInt32(nFlags);
4782
4783 PPTTextSpecInfo aEntry( nCharIdx );
4784 if ( pTextSpecDefault )
4785 {
4786 aEntry.nDontKnow = pTextSpecDefault->nDontKnow;
4787 aEntry.nLanguage[ 0 ] = pTextSpecDefault->nLanguage[ 0 ];
4788 aEntry.nLanguage[ 1 ] = pTextSpecDefault->nLanguage[ 1 ];
4789 aEntry.nLanguage[ 2 ] = pTextSpecDefault->nLanguage[ 2 ];
4790 }
4791 for (sal_uInt32 i = 1; nFlags && i ; i <<= 1)
4792 {
4793 sal_uInt16 nLang = 0;
4794 switch( nFlags & i )
4795 {
4796 case 0 : break;
4797 case 1 : rIn.ReadUInt16( aEntry.nDontKnow ); break;
4798 case 2 : rIn.ReadUInt16( nLang ); break;
4799 case 4 : rIn.ReadUInt16( nLang ); break;
4800 default :
4801 {
4802 rIn.SeekRel( 2 );
4803 }
4804 }
4805 if ( nLang )
4806 {
4807 // #i119985#, we could probably handle this better if we have a
4808 // place to override the final language for weak
4809 // characters/fields to fallback to, rather than the current
4810 // application locale. Assuming that we can determine what the
4811 // default fallback language for a given .ppt, etc is during
4812 // load time.
4813 if (i == 2)
4814 {
4815 aEntry.nLanguage[ 0 ] = aEntry.nLanguage[ 1 ] = aEntry.nLanguage[ 2 ] = LanguageType(nLang);
4816 }
4817 }
4818 nFlags &= ~i;
4819 }
4820 aList.push_back( aEntry );
4821 }
4822 bValid = rIn.Tell() == rRecHd.GetRecEndFilePos();
4823 return bValid;
4824 }
4825
~PPTTextSpecInfoAtomInterpreter()4826 PPTTextSpecInfoAtomInterpreter::~PPTTextSpecInfoAtomInterpreter()
4827 {
4828 }
4829
Read(SvStream & rIn)4830 void StyleTextProp9::Read( SvStream& rIn )
4831 {
4832 rIn.ReadUInt32( mnExtParagraphMask );
4833 if ( mnExtParagraphMask & 0x800000 )
4834 rIn.ReadUInt16( mnBuBlip );
4835 if ( mnExtParagraphMask & 0x2000000 )
4836 rIn.ReadUInt16( mnHasAnm );
4837 if ( mnExtParagraphMask & 0x1000000 )
4838 rIn.ReadUInt32( mnAnmScheme );
4839 if ( mnExtParagraphMask & 0x4000000 )
4840 rIn.ReadUInt32( mpfPP10Ext );
4841 rIn.ReadUInt32( mnExtCharacterMask );
4842 if ( mnExtCharacterMask & 0x100000 )
4843 rIn.ReadUInt32( mncfPP10Ext );
4844 rIn.ReadUInt32( mnSpecialInfoMask );
4845 if ( mnSpecialInfoMask & 0x20 )
4846 rIn.ReadUInt32( mnPP10Ext );
4847 if ( mnSpecialInfoMask & 0x40 )
4848 rIn.ReadUInt16( mfBidi );
4849 }
4850
PPTStyleTextPropReader(SvStream & rIn,const DffRecordHeader & rTextHeader,PPTTextRulerInterpreter const & rRuler,const DffRecordHeader & rExtParaHd,TSS_Type nInstance)4851 PPTStyleTextPropReader::PPTStyleTextPropReader( SvStream& rIn, const DffRecordHeader& rTextHeader,
4852 PPTTextRulerInterpreter const & rRuler, const DffRecordHeader& rExtParaHd, TSS_Type nInstance )
4853 {
4854 Init(rIn, rTextHeader, rRuler, rExtParaHd, nInstance);
4855 }
4856
ReadParaProps(SvStream & rIn,const DffRecordHeader & rTextHeader,const OUString & aString,PPTTextRulerInterpreter const & rRuler,sal_uInt32 & nCharCount,bool & bTextPropAtom)4857 void PPTStyleTextPropReader::ReadParaProps( SvStream& rIn, const DffRecordHeader& rTextHeader,
4858 const OUString& aString, PPTTextRulerInterpreter const & rRuler,
4859 sal_uInt32& nCharCount, bool& bTextPropAtom )
4860 {
4861 sal_uInt32 nMask = 0; //TODO: nMask initialized here to suppress warning for now, see corresponding TODO below
4862 sal_uInt32 nCharReadCnt = 0;
4863 sal_uInt16 nDummy16;
4864
4865 sal_uInt16 nStringLen = aString.getLength();
4866
4867 DffRecordHeader aTextHd2;
4868 rTextHeader.SeekToContent( rIn );
4869 if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_StyleTextPropAtom, rTextHeader.GetRecEndFilePos(), &aTextHd2 ) )
4870 bTextPropAtom = true;
4871 while ( nCharReadCnt <= nStringLen )
4872 {
4873 PPTParaPropSet aParaPropSet;
4874 ImplPPTParaPropSet& aSet = *aParaPropSet.mxParaSet;
4875 if ( bTextPropAtom )
4876 {
4877 rIn.ReadUInt32( nCharCount )
4878 .ReadUInt16( aParaPropSet.mxParaSet->mnDepth ); // indent depth
4879
4880 aParaPropSet.mxParaSet->mnDepth = // taking care of about using not more than 9 outliner levels
4881 std::min(sal_uInt16(8),
4882 aParaPropSet.mxParaSet->mnDepth);
4883
4884 nCharCount--;
4885
4886 rIn.ReadUInt32( nMask );
4887 aSet.mnAttrSet = nMask & 0x207df7;
4888 sal_uInt16 nBulFlg = 0;
4889 if ( nMask & 0xF )
4890 rIn.ReadUInt16( nBulFlg ); // Bullet-HardAttr-Flags
4891 aSet.mpArry[ PPT_ParaAttr_BulletOn ] = ( nBulFlg & 1 ) ? 1 : 0;
4892 aSet.mpArry[ PPT_ParaAttr_BuHardFont ] = ( nBulFlg & 2 ) ? 1 : 0;
4893 aSet.mpArry[ PPT_ParaAttr_BuHardColor ] = ( nBulFlg & 4 ) ? 1 : 0;
4894
4895 // NOTE: one might think that the hard-coded numbers here are the
4896 // same as the PPT_ParaAttr_* constants, but it's NOT always true!
4897 if ( nMask & 0x0080 ) // buChar
4898 {
4899 rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_BulletChar ] );
4900 if (!rIn.good())
4901 {
4902 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_BulletChar);
4903 }
4904 }
4905 if ( nMask & 0x0010 ) // buTypeface
4906 {
4907 rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_BulletFont ] );
4908 if (!rIn.good())
4909 {
4910 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_BulletFont);
4911 }
4912 }
4913 if ( nMask & 0x0040 ) // buSize
4914 {
4915 rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_BulletHeight ] );
4916 if (!rIn.good()
4917 || !((nMask & (1 << PPT_ParaAttr_BuHardHeight))
4918 && (nBulFlg & (1 << PPT_ParaAttr_BuHardHeight))))
4919 {
4920 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_BulletHeight);
4921 }
4922 }
4923 if ( nMask & 0x0020 ) // buColor
4924 {
4925 sal_uInt32 nVal32;
4926 rIn.ReadUInt32( nVal32 );
4927 if (!rIn.good())
4928 {
4929 aSet.mnBulletColor = 0; // no flag for this? default it
4930 }
4931 else
4932 {
4933 sal_uInt32 nHiByte;
4934 nHiByte = nVal32 >> 24;
4935 if ( nHiByte <= 8 )
4936 nVal32 = nHiByte | PPT_COLSCHEME;
4937 aSet.mnBulletColor = nVal32;
4938 }
4939 }
4940 if ( nMask & 0x0800 ) // pfAlignment
4941 {
4942 rIn.ReadUInt16( nDummy16 );
4943 if (!rIn.good())
4944 {
4945 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_Adjust);
4946 }
4947 else
4948 {
4949 aSet.mpArry[ PPT_ParaAttr_Adjust ] = nDummy16 & 3;
4950 }
4951 }
4952 if ( nMask & 0x1000 ) // pfLineSpacing
4953 {
4954 rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_LineFeed ] );
4955 if (!rIn.good())
4956 {
4957 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_LineFeed);
4958 }
4959 }
4960 if ( nMask & 0x2000 ) // pfSpaceBefore
4961 {
4962 rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_UpperDist ] );
4963 if (!rIn.good())
4964 {
4965 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_UpperDist);
4966 }
4967 }
4968 if ( nMask & 0x4000 ) // pfSpaceAfter
4969 {
4970 rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_LowerDist ] );
4971 if (!rIn.good())
4972 {
4973 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_LowerDist);
4974 }
4975 }
4976 if ( nMask & 0x100 ) // pfLeftMargin
4977 {
4978 rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_TextOfs ] );
4979 if (!rIn.good())
4980 {
4981 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_TextOfs);
4982 }
4983 else
4984 {
4985 aSet.mnAttrSet |= 1 << PPT_ParaAttr_TextOfs;
4986 }
4987 }
4988 if ( nMask & 0x400 ) // pfIndent
4989 {
4990 rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_BulletOfs ] );
4991 if (!rIn.good())
4992 {
4993 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_BulletOfs);
4994 }
4995 else
4996 {
4997 aSet.mnAttrSet |= 1 << PPT_ParaAttr_BulletOfs;
4998 }
4999 }
5000 if ( nMask & 0x8000 ) // pfDefaultTabSize
5001 {
5002 rIn.ReadUInt16( nDummy16 );
5003 if (!rIn.good())
5004 {
5005 // TODO?
5006 }
5007 }
5008 if ( nMask & 0x100000 ) // pfTabStops
5009 {
5010 sal_uInt16 i, nDistance, nAlignment, nNumberOfTabStops = 0;
5011 rIn.ReadUInt16( nNumberOfTabStops );
5012 if (!rIn.good())
5013 {
5014 // TODO?
5015 }
5016 else
5017 {
5018 const size_t nMinRecordSize = 4;
5019 const size_t nMaxRecords = rIn.remainingSize() / nMinRecordSize;
5020 if (nNumberOfTabStops > nMaxRecords)
5021 {
5022 SAL_WARN("filter.ms", "Parsing error: " << nMaxRecords <<
5023 " max possible entries, but " << nNumberOfTabStops << " claimed, truncating");
5024 nNumberOfTabStops = nMaxRecords;
5025 }
5026 for (i = 0; i < nNumberOfTabStops; ++i)
5027 {
5028 rIn.ReadUInt16( nDistance )
5029 .ReadUInt16( nAlignment );
5030 }
5031 }
5032 }
5033 if ( nMask & 0x10000 ) // pfBaseLine
5034 {
5035 rIn.ReadUInt16( nDummy16 );
5036 if (!rIn.good())
5037 {
5038 // TODO?
5039 }
5040 }
5041 if ( nMask & 0xe0000 ) // pfCharWrap, pfWordWrap, pfOverflow
5042 {
5043 rIn.ReadUInt16( nDummy16 );
5044 if (!rIn.good())
5045 { // clear flag to avoid invalid access
5046 aSet.mnAttrSet &= ~((1 << PPT_ParaAttr_AsianLB_1)
5047 | (1 << PPT_ParaAttr_AsianLB_2)
5048 | (1 << PPT_ParaAttr_AsianLB_3));
5049 }
5050 else
5051 {
5052 if (nMask & 0x20000)
5053 aSet.mpArry[PPT_ParaAttr_AsianLB_1] = nDummy16 & 1;
5054 if (nMask & 0x40000)
5055 aSet.mpArry[PPT_ParaAttr_AsianLB_2] = (nDummy16 >> 1) & 1;
5056 if (nMask & 0x80000)
5057 aSet.mpArry[PPT_ParaAttr_AsianLB_3] = (nDummy16 >> 2) & 1;
5058 aSet.mnAttrSet |= ((nMask >> 17) & 7) << PPT_ParaAttr_AsianLB_1;
5059 }
5060 }
5061 if ( nMask & 0x200000 ) // pfTextDirection
5062 {
5063 rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_BiDi ] );
5064 if (!rIn.good())
5065 { // clear flag to avoid invalid access
5066 aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_BiDi);
5067 }
5068 }
5069 }
5070 else
5071 nCharCount = nStringLen;
5072
5073 //if the textofs attr has been read at above, need not to reset.
5074 if ( ( !( aSet.mnAttrSet & 1 << PPT_ParaAttr_TextOfs ) ) && rRuler.GetTextOfs( aParaPropSet.mxParaSet->mnDepth, aSet.mpArry[ PPT_ParaAttr_TextOfs ] ) )
5075 aSet.mnAttrSet |= 1 << PPT_ParaAttr_TextOfs;
5076 if ( ( !( aSet.mnAttrSet & 1 << PPT_ParaAttr_BulletOfs ) ) && rRuler.GetBulletOfs( aParaPropSet.mxParaSet->mnDepth, aSet.mpArry[ PPT_ParaAttr_BulletOfs ] ) )
5077 aSet.mnAttrSet |= 1 << PPT_ParaAttr_BulletOfs;
5078 if ( rRuler.GetDefaultTab( aSet.mpArry[ PPT_ParaAttr_DefaultTab ] ) )
5079 aSet.mnAttrSet |= 1 << PPT_ParaAttr_DefaultTab;
5080
5081 if ( ( nCharCount > nStringLen ) || ( nStringLen < nCharReadCnt + nCharCount ) )
5082 {
5083 bTextPropAtom = false;
5084 nCharCount = nStringLen - nCharReadCnt;
5085 // please fix the right hand side of
5086 // PPTParaPropSet& PPTParaPropSet::operator=(PPTParaPropSet&),
5087 // it should be a const reference
5088 PPTParaPropSet aTmpPPTParaPropSet;
5089 aParaPropSet = aTmpPPTParaPropSet;
5090 OSL_FAIL( "SJ:PPTStyleTextPropReader::could not get this PPT_PST_StyleTextPropAtom by reading the paragraph attributes" );
5091 }
5092 PPTParaPropSet* pPara = new PPTParaPropSet( aParaPropSet );
5093 pPara->mnOriginalTextPos = nCharReadCnt;
5094 aParaPropList.emplace_back( pPara );
5095 if ( nCharCount )
5096 {
5097 sal_uInt32 nCount;
5098 const sal_Unicode* pDat = aString.getStr() + nCharReadCnt;
5099 for ( nCount = 0; nCount < nCharCount; nCount++ )
5100 {
5101 if ( pDat[ nCount ] == 0xd )
5102 {
5103 pPara = new PPTParaPropSet( aParaPropSet );
5104 pPara->mnOriginalTextPos = nCharReadCnt + nCount + 1;
5105 aParaPropList.emplace_back( pPara );
5106 }
5107 }
5108 }
5109 nCharReadCnt += nCharCount + 1;
5110 }
5111 }
5112
ReadCharProps(SvStream & rIn,PPTCharPropSet & aCharPropSet,const OUString & aString,sal_uInt32 & nCharCount,sal_uInt32 nCharReadCnt,bool & bTextPropAtom,sal_uInt32 nExtParaPos,const std::vector<StyleTextProp9> & aStyleTextProp9,sal_uInt32 & nExtParaFlags,sal_uInt16 & nBuBlip,sal_uInt16 & nHasAnm,sal_uInt32 & nAnmScheme)5113 void PPTStyleTextPropReader::ReadCharProps( SvStream& rIn, PPTCharPropSet& aCharPropSet, const OUString& aString,
5114 sal_uInt32& nCharCount, sal_uInt32 nCharReadCnt,
5115 bool& bTextPropAtom, sal_uInt32 nExtParaPos,
5116 const std::vector< StyleTextProp9 >& aStyleTextProp9,
5117 sal_uInt32& nExtParaFlags, sal_uInt16& nBuBlip,
5118 sal_uInt16& nHasAnm, sal_uInt32& nAnmScheme )
5119 {
5120 sal_uInt32 nMask = 0; //TODO: nMask initialized here to suppress warning for now, see corresponding TODO below
5121 sal_uInt16 nDummy16;
5122 sal_Int32 nCharsToRead;
5123 sal_uInt16 nStringLen = aString.getLength();
5124
5125 rIn.ReadUInt16( nDummy16 );
5126 nCharCount = (rIn.good()) ? nDummy16 : 0;
5127 rIn.ReadUInt16( nDummy16 );
5128 nCharsToRead = nStringLen - ( nCharReadCnt + nCharCount );
5129 if ( nCharsToRead < 0 )
5130 {
5131 nCharCount = nStringLen - nCharReadCnt;
5132 if ( nCharsToRead < -1 )
5133 {
5134 bTextPropAtom = false;
5135 OSL_FAIL( "SJ:PPTStyleTextPropReader::could not get this PPT_PST_StyleTextPropAtom by reading the character attributes" );
5136 }
5137 }
5138 ImplPPTCharPropSet& aSet = *aCharPropSet.mpImplPPTCharPropSet;
5139
5140 // character attributes
5141 rIn.ReadUInt32( nMask );
5142 if ( static_cast<sal_uInt16>(nMask) )
5143 {
5144 aSet.mnAttrSet |= static_cast<sal_uInt16>(nMask);
5145 rIn.ReadUInt16( aSet.mnFlags );
5146 }
5147 if ( nMask & 0x10000 ) // cfTypeface
5148 {
5149 rIn.ReadUInt16( aSet.mnFont );
5150 aSet.mnAttrSet |= 1 << PPT_CharAttr_Font;
5151 }
5152 if ( nMask & 0x200000 ) // cfFEOldTypeface
5153 {
5154 rIn.ReadUInt16( aSet.mnAsianOrComplexFont );
5155 aSet.mnAttrSet |= 1 << PPT_CharAttr_AsianOrComplexFont;
5156 }
5157 if ( nMask & 0x400000 ) // cfANSITypeface
5158 {
5159 rIn.ReadUInt16( aSet.mnANSITypeface );
5160 aSet.mnAttrSet |= 1 << PPT_CharAttr_ANSITypeface;
5161 }
5162 if ( nMask & 0x800000 ) // cfSymbolTypeface
5163 {
5164 rIn.ReadUInt16( aSet.mnSymbolFont );
5165 aSet.mnAttrSet |= 1 << PPT_CharAttr_Symbol;
5166 }
5167 if ( nMask & 0x20000 ) // cfSize
5168 {
5169 rIn.ReadUInt16( aSet.mnFontHeight );
5170 aSet.mnAttrSet |= 1 << PPT_CharAttr_FontHeight;
5171 }
5172 if ( nMask & 0x40000 ) // cfColor
5173 {
5174 sal_uInt32 nVal;
5175 rIn.ReadUInt32( nVal );
5176 if ( !( nVal & 0xff000000 ) )
5177 nVal = PPT_COLSCHEME_HINTERGRUND;
5178 aSet.mnColor = nVal;
5179 aSet.mnAttrSet |= 1 << PPT_CharAttr_FontColor;
5180 }
5181 if ( nMask & 0x80000 ) // cfPosition
5182 {
5183 rIn.ReadUInt16( aSet.mnEscapement );
5184 aSet.mnAttrSet |= 1 << PPT_CharAttr_Escapement;
5185 }
5186 if ( !nExtParaPos )
5187 return;
5188
5189 sal_uInt32 nExtBuInd = nMask & 0x3c00;
5190 if ( nExtBuInd )
5191 nExtBuInd = ( aSet.mnFlags & 0x3c00 ) >> 10;
5192 if ( nExtBuInd < aStyleTextProp9.size() )
5193 {
5194 nExtParaFlags = aStyleTextProp9[ nExtBuInd ].mnExtParagraphMask;
5195 nBuBlip = aStyleTextProp9[ nExtBuInd ].mnBuBlip;
5196 nHasAnm = aStyleTextProp9[ nExtBuInd ].mnHasAnm;
5197 nAnmScheme = aStyleTextProp9[ nExtBuInd ].mnAnmScheme;
5198 }
5199 }
5200
Init(SvStream & rIn,const DffRecordHeader & rTextHeader,PPTTextRulerInterpreter const & rRuler,const DffRecordHeader & rExtParaHd,TSS_Type nInstance)5201 void PPTStyleTextPropReader::Init( SvStream& rIn, const DffRecordHeader& rTextHeader,
5202 PPTTextRulerInterpreter const & rRuler, const DffRecordHeader& rExtParaHd, TSS_Type nInstance )
5203 {
5204 sal_uInt32 nOldPos = rIn.Tell();
5205 sal_uInt32 nExtParaPos = ( rExtParaHd.nRecType == PPT_PST_ExtendedParagraphAtom ) ? rExtParaHd.nFilePos + 8 : 0;
5206
5207 std::vector< StyleTextProp9 > aStyleTextProp9;
5208 if ( rExtParaHd.nRecType == PPT_PST_ExtendedParagraphAtom )
5209 {
5210 rIn.Seek( rExtParaHd.nFilePos + 8 );
5211
5212 auto nEndRecPos = DffPropSet::SanitizeEndPos(rIn, rExtParaHd.GetRecEndFilePos());
5213 while( ( rIn.GetError() == ERRCODE_NONE ) && ( rIn.Tell() < nEndRecPos ) )
5214 {
5215 aStyleTextProp9.emplace_back();
5216 aStyleTextProp9.back().Read( rIn );
5217 }
5218 rIn.Seek( nOldPos );
5219 }
5220
5221 OUString aString;
5222 DffRecordHeader aTextHd;
5223 ReadDffRecordHeader( rIn, aTextHd );
5224 sal_uInt32 nMaxLen = aTextHd.nRecLen;
5225 if ( nMaxLen >= 0xFFFF )
5226 nMaxLen = 0xFFFE;
5227
5228 if( aTextHd.nRecType == PPT_PST_TextCharsAtom )
5229 {
5230 sal_uInt32 i;
5231 sal_Unicode nChar;
5232 std::unique_ptr<sal_Unicode[]> pBuf(new sal_Unicode[ ( nMaxLen >> 1 ) + 1 ]);
5233 rIn.ReadBytes(pBuf.get(), nMaxLen);
5234 nMaxLen >>= 1;
5235 pBuf[ nMaxLen ] = 0;
5236 sal_Unicode* pPtr = pBuf.get();
5237 #ifdef OSL_BIGENDIAN
5238 sal_Unicode nTemp;
5239 for ( i = 0; i < nMaxLen; i++ )
5240 {
5241 nTemp = *pPtr;
5242 *pPtr++ = ( nTemp << 8 ) | ( nTemp >> 8 );
5243 }
5244 pPtr = pBuf.get();
5245 #endif
5246
5247 for ( i = 0; i < nMaxLen; pPtr++, i++ )
5248 {
5249 nChar = *pPtr;
5250 if ( !nChar )
5251 break;
5252 if ( ( nChar & 0xff00 ) == 0xf000 ) // in this special case we got a symbol
5253 aSpecMarkerList.push_back( static_cast<sal_uInt32>( i | PPT_SPEC_SYMBOL ) );
5254 else if ( nChar == 0xd )
5255 {
5256 if ( nInstance == TSS_Type::PageTitle )
5257 *pPtr = 0xb;
5258 else
5259 aSpecMarkerList.push_back( static_cast<sal_uInt32>( i | PPT_SPEC_NEWLINE ) );
5260 }
5261 }
5262 if ( i )
5263 aString = OUString(pBuf.get(), i);
5264 }
5265 else if( aTextHd.nRecType == PPT_PST_TextBytesAtom )
5266 {
5267 std::unique_ptr<char[]> pBuf(new char[ nMaxLen + 1 ]);
5268 pBuf[ nMaxLen ] = 0;
5269 rIn.ReadBytes(pBuf.get(), nMaxLen);
5270 char* pPtr = pBuf.get();
5271 for (;;)
5272 {
5273 char cLo = *pPtr;
5274 if ( cLo == 0 )
5275 break;
5276 if ( cLo == 0xd )
5277 {
5278 if ( nInstance == TSS_Type::PageTitle )
5279 *pPtr = 0xb;
5280 else
5281 aSpecMarkerList.push_back( static_cast<sal_uInt32>( (pPtr - pBuf.get()) | PPT_SPEC_NEWLINE ) );
5282 }
5283 pPtr++;
5284 }
5285 sal_Int32 nLen = pPtr - pBuf.get();
5286 if ( nLen )
5287 aString = OUString( pBuf.get(), nLen, RTL_TEXTENCODING_MS_1252 );
5288 }
5289 else
5290 {
5291 // no chars, but potentially char/para props?
5292 sal_uInt32 nCharCount;
5293 bool bTextPropAtom = false;
5294 ReadParaProps( rIn, rTextHeader, aString, rRuler, nCharCount, bTextPropAtom );
5295
5296 if ( bTextPropAtom )
5297 {
5298 // yeah, StyleTextProp is there, read it all & push to
5299 // aParaPropList
5300 PPTCharPropSet aCharPropSet(0);
5301 aCharPropSet.mnOriginalTextPos = 0;
5302
5303 sal_uInt32 nExtParaFlags = 0, nAnmScheme = 0;
5304 sal_uInt16 nBuBlip = 0xffff, nHasAnm = 0;
5305 ReadCharProps( rIn, aCharPropSet, aString, nCharCount, 0/*nCharReadCnt*/,
5306 bTextPropAtom, nExtParaPos, aStyleTextProp9, nExtParaFlags,
5307 nBuBlip, nHasAnm, nAnmScheme );
5308
5309 aCharPropList.push_back(std::make_unique<PPTCharPropSet>(aCharPropSet, 0));
5310 }
5311 }
5312
5313 if ( !aString.isEmpty() )
5314 {
5315 sal_uInt32 nCharCount;
5316 bool bTextPropAtom = false;
5317
5318 ReadParaProps( rIn, rTextHeader, aString, rRuler, nCharCount, bTextPropAtom );
5319
5320 bool bEmptyParaPossible = true;
5321 sal_uInt32 nCharReadCnt = 0;
5322 sal_uInt32 nCurrentPara = 0;
5323 size_t i = 1; // points to the next element to process
5324 sal_uInt32 nCurrentSpecMarker = aSpecMarkerList.empty() ? 0 : aSpecMarkerList[0];
5325 sal_uInt32 nStringLen = aString.getLength();
5326
5327 while ( nCharReadCnt < nStringLen )
5328 {
5329 sal_uInt32 nExtParaFlags = 0, nLatestParaUpdate = 0xffffffff, nAnmScheme = 0;
5330 sal_uInt16 nBuBlip = 0xffff, nHasAnm = 0;
5331
5332 PPTCharPropSet aCharPropSet( nCurrentPara );
5333 if ( bTextPropAtom )
5334 {
5335 ReadCharProps( rIn, aCharPropSet, aString, nCharCount, nCharReadCnt,
5336 bTextPropAtom, nExtParaPos, aStyleTextProp9, nExtParaFlags,
5337 nBuBlip, nHasAnm, nAnmScheme );
5338 if (!rIn.good())
5339 break;
5340 }
5341 else
5342 nCharCount = nStringLen;
5343
5344 sal_uInt32 nLen;
5345 while( nCharCount )
5346 {
5347 if ( nExtParaPos && ( nLatestParaUpdate != nCurrentPara ) && ( nCurrentPara < aParaPropList.size() ) )
5348 {
5349 PPTParaPropSet* pPropSet = aParaPropList[ nCurrentPara ].get();
5350 pPropSet->mxParaSet->mnExtParagraphMask = nExtParaFlags;
5351 if ( nExtParaFlags & 0x800000 )
5352 pPropSet->mxParaSet->mnBuBlip = nBuBlip;
5353 if ( nExtParaFlags & 0x01000000 )
5354 pPropSet->mxParaSet->mnAnmScheme = nAnmScheme;
5355 if ( nExtParaFlags & 0x02000000 )
5356 pPropSet->mxParaSet->mnHasAnm = nHasAnm;
5357 nLatestParaUpdate = nCurrentPara;
5358 }
5359 aCharPropSet.mnOriginalTextPos = nCharReadCnt;
5360 if ( nCurrentSpecMarker && ( ( nCurrentSpecMarker & 0xffff ) < ( nCharReadCnt + nCharCount ) ) )
5361 {
5362 if ( nCurrentSpecMarker & PPT_SPEC_NEWLINE )
5363 {
5364 nLen = ( nCurrentSpecMarker & 0xffff ) - nCharReadCnt;
5365 if ( nLen )
5366 aCharPropSet.maString = aString.copy( nCharReadCnt, nLen );
5367 else if ( bEmptyParaPossible )
5368 aCharPropSet.maString.clear();
5369 if ( nLen || bEmptyParaPossible )
5370 aCharPropList.push_back(
5371 std::make_unique<PPTCharPropSet>(aCharPropSet, nCurrentPara));
5372 nCurrentPara++;
5373 nLen++;
5374 nCharReadCnt += nLen;
5375 nCharCount -= nLen;
5376 bEmptyParaPossible = true;
5377 }
5378 else if ( nCurrentSpecMarker & PPT_SPEC_SYMBOL )
5379 {
5380 if ( ( nCurrentSpecMarker & 0xffff ) != nCharReadCnt )
5381 {
5382 nLen = ( nCurrentSpecMarker & 0xffff ) - nCharReadCnt;
5383 aCharPropSet.maString = aString.copy(nCharReadCnt, nLen);
5384 aCharPropList.push_back(
5385 std::make_unique<PPTCharPropSet>(aCharPropSet, nCurrentPara));
5386 nCharCount -= nLen;
5387 nCharReadCnt += nLen;
5388 }
5389 PPTCharPropSet* pCPropSet = new PPTCharPropSet( aCharPropSet, nCurrentPara );
5390 pCPropSet->maString = aString.copy(nCharReadCnt, 1);
5391 if ( aCharPropSet.mpImplPPTCharPropSet->mnAttrSet & ( 1 << PPT_CharAttr_Symbol ) )
5392 pCPropSet->SetFont( aCharPropSet.mpImplPPTCharPropSet->mnSymbolFont );
5393 aCharPropList.emplace_back( pCPropSet );
5394 nCharCount--;
5395 nCharReadCnt++;
5396 bEmptyParaPossible = false;
5397 }
5398 nCurrentSpecMarker = ( i < aSpecMarkerList.size() ) ? aSpecMarkerList[ i++ ] : 0;
5399 }
5400 else
5401 {
5402 if (nCharReadCnt > o3tl::make_unsigned(aString.getLength()))
5403 aCharPropSet.maString = OUString();
5404 else
5405 {
5406 sal_Int32 nStrLen = nCharCount;
5407 sal_Int32 nMaxStrLen = aString.getLength() - nCharReadCnt;
5408 if (nStrLen > nMaxStrLen)
5409 nStrLen = nMaxStrLen;
5410 aCharPropSet.maString = aString.copy(nCharReadCnt, nStrLen);
5411 }
5412 aCharPropList.push_back(
5413 std::make_unique<PPTCharPropSet>(aCharPropSet, nCurrentPara));
5414 nCharReadCnt += nCharCount;
5415 bEmptyParaPossible = false;
5416 break;
5417 }
5418 }
5419 }
5420 if ( !aCharPropList.empty() && ( aCharPropList.back()->mnParagraph != nCurrentPara ) )
5421 {
5422 PPTCharPropSet* pCharPropSet = new PPTCharPropSet( *aCharPropList.back(), nCurrentPara );
5423 pCharPropSet->maString.clear();
5424 pCharPropSet->mnOriginalTextPos = nStringLen - 1;
5425 aCharPropList.emplace_back( pCharPropSet );
5426 }
5427 }
5428 rIn.Seek( nOldPos );
5429 }
5430
~PPTStyleTextPropReader()5431 PPTStyleTextPropReader::~PPTStyleTextPropReader()
5432 {
5433 }
5434
PPTPortionObj(const PPTStyleSheet & rStyleSheet,TSS_Type nInstance,sal_uInt32 nDepth)5435 PPTPortionObj::PPTPortionObj( const PPTStyleSheet& rStyleSheet, TSS_Type nInstance, sal_uInt32 nDepth ) :
5436 PPTCharPropSet ( 0 ),
5437 mrStyleSheet ( rStyleSheet ),
5438 mnInstance ( nInstance ),
5439 mnDepth ( std::min<sal_uInt32>( nDepth, 4 ) )
5440 {
5441 }
5442
PPTPortionObj(const PPTCharPropSet & rCharPropSet,const PPTStyleSheet & rStyleSheet,TSS_Type nInstance,sal_uInt32 nDepth)5443 PPTPortionObj::PPTPortionObj( const PPTCharPropSet& rCharPropSet, const PPTStyleSheet& rStyleSheet, TSS_Type nInstance, sal_uInt32 nDepth ) :
5444 PPTCharPropSet ( rCharPropSet ),
5445 mrStyleSheet ( rStyleSheet ),
5446 mnInstance ( nInstance ),
5447 mnDepth ( std::min<sal_uInt32>( nDepth, 4 ) )
5448 {
5449 }
5450
PPTPortionObj(const PPTPortionObj & rPortionObj)5451 PPTPortionObj::PPTPortionObj( const PPTPortionObj& rPortionObj ) :
5452 PPTCharPropSet ( rPortionObj ),
5453 mrStyleSheet ( rPortionObj.mrStyleSheet ),
5454 mnInstance ( rPortionObj.mnInstance ),
5455 mnDepth ( rPortionObj.mnDepth )
5456 {
5457 }
5458
~PPTPortionObj()5459 PPTPortionObj::~PPTPortionObj()
5460 {
5461 }
5462
GetAttrib(sal_uInt32 nAttr,sal_uInt32 & rRetValue,TSS_Type nDestinationInstance) const5463 bool PPTPortionObj::GetAttrib( sal_uInt32 nAttr, sal_uInt32& rRetValue, TSS_Type nDestinationInstance ) const
5464 {
5465 sal_uInt32 nMask = 1 << nAttr;
5466 rRetValue = 0;
5467
5468 bool bIsHardAttribute = ( ( mpImplPPTCharPropSet->mnAttrSet & nMask ) != 0 );
5469
5470 if ( bIsHardAttribute )
5471 {
5472 switch ( nAttr )
5473 {
5474 case PPT_CharAttr_Bold :
5475 case PPT_CharAttr_Italic :
5476 case PPT_CharAttr_Underline :
5477 case PPT_CharAttr_Shadow :
5478 case PPT_CharAttr_Strikeout :
5479 case PPT_CharAttr_Embossed :
5480 rRetValue = ( mpImplPPTCharPropSet->mnFlags & nMask ) ? 1 : 0;
5481 break;
5482 case PPT_CharAttr_Font :
5483 rRetValue = mpImplPPTCharPropSet->mnFont;
5484 break;
5485 case PPT_CharAttr_AsianOrComplexFont :
5486 rRetValue = mpImplPPTCharPropSet->mnAsianOrComplexFont;
5487 break;
5488 case PPT_CharAttr_FontHeight :
5489 rRetValue = mpImplPPTCharPropSet->mnFontHeight;
5490 break;
5491 case PPT_CharAttr_FontColor :
5492 rRetValue = mpImplPPTCharPropSet->mnColor;
5493 break;
5494 case PPT_CharAttr_Escapement :
5495 rRetValue = mpImplPPTCharPropSet->mnEscapement;
5496 break;
5497 default :
5498 OSL_FAIL( "SJ:PPTPortionObj::GetAttrib ( hard attribute does not exist )" );
5499 }
5500 }
5501 else
5502 {
5503 const PPTCharLevel& rCharLevel = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[ mnDepth ];
5504 PPTCharLevel* pCharLevel = nullptr;
5505 if ( ( nDestinationInstance == TSS_Type::Unknown )
5506 || ( mnDepth && ( ( mnInstance == TSS_Type::Subtitle ) || ( mnInstance == TSS_Type::TextInShape ) ) ) )
5507 bIsHardAttribute = true;
5508 else if ( nDestinationInstance != mnInstance )
5509 pCharLevel = &mrStyleSheet.mpCharSheet[ nDestinationInstance ]->maCharLevel[ mnDepth ];
5510 switch( nAttr )
5511 {
5512 case PPT_CharAttr_Bold :
5513 case PPT_CharAttr_Italic :
5514 case PPT_CharAttr_Underline :
5515 case PPT_CharAttr_Shadow :
5516 case PPT_CharAttr_Strikeout :
5517 case PPT_CharAttr_Embossed :
5518 {
5519 rRetValue = ( rCharLevel.mnFlags & nMask ) ? 1 : 0;
5520 if ( pCharLevel )
5521 {
5522 sal_uInt32 nTmp = ( pCharLevel->mnFlags & nMask ) ? 1 : 0;
5523 if ( rRetValue != nTmp )
5524 bIsHardAttribute = true;
5525 }
5526 }
5527 break;
5528 case PPT_CharAttr_Font :
5529 {
5530 rRetValue = rCharLevel.mnFont;
5531 if ( pCharLevel && ( rRetValue != pCharLevel->mnFont ) )
5532 bIsHardAttribute = true;
5533 }
5534 break;
5535 case PPT_CharAttr_AsianOrComplexFont :
5536 {
5537 rRetValue = rCharLevel.mnAsianOrComplexFont;
5538 if ( pCharLevel && ( rRetValue != pCharLevel->mnAsianOrComplexFont ) )
5539 bIsHardAttribute = true;
5540 }
5541 break;
5542 case PPT_CharAttr_FontHeight :
5543 {
5544 rRetValue = rCharLevel.mnFontHeight;
5545 if ( pCharLevel && ( rRetValue != pCharLevel->mnFontHeight ) )
5546 bIsHardAttribute = true;
5547 }
5548 break;
5549 case PPT_CharAttr_FontColor :
5550 {
5551 rRetValue = rCharLevel.mnFontColor;
5552 if ( pCharLevel && ( rRetValue != pCharLevel->mnFontColor ) )
5553 bIsHardAttribute = true;
5554 }
5555 break;
5556 case PPT_CharAttr_Escapement :
5557 {
5558 rRetValue = rCharLevel.mnEscapement;
5559 if ( pCharLevel && ( rRetValue != pCharLevel->mnEscapement ) )
5560 bIsHardAttribute = true;
5561 }
5562 break;
5563 default :
5564 OSL_FAIL( "SJ:PPTPortionObj::GetAttrib ( attribute does not exist )" );
5565 }
5566 }
5567 return bIsHardAttribute;
5568 }
5569
ApplyTo(SfxItemSet & rSet,SdrPowerPointImport & rManager,TSS_Type nDestinationInstance)5570 void PPTPortionObj::ApplyTo( SfxItemSet& rSet, SdrPowerPointImport& rManager, TSS_Type nDestinationInstance )
5571 {
5572 ApplyTo( rSet, rManager, nDestinationInstance, nullptr );
5573 }
5574
ApplyTo(SfxItemSet & rSet,SdrPowerPointImport & rManager,TSS_Type nDestinationInstance,const PPTTextObj * pTextObj)5575 void PPTPortionObj::ApplyTo( SfxItemSet& rSet, SdrPowerPointImport& rManager, TSS_Type nDestinationInstance, const PPTTextObj* pTextObj )
5576 {
5577 sal_uInt32 nVal;
5578 if ( GetAttrib( PPT_CharAttr_Bold, nVal, nDestinationInstance ) )
5579 {
5580 rSet.Put( SvxWeightItem( nVal != 0 ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT ) );
5581 rSet.Put( SvxWeightItem( nVal != 0 ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT_CJK ) );
5582 rSet.Put( SvxWeightItem( nVal != 0 ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT_CTL ) );
5583 }
5584 if ( GetAttrib( PPT_CharAttr_Italic, nVal, nDestinationInstance ) )
5585 {
5586 rSet.Put( SvxPostureItem( nVal != 0 ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC ) );
5587 rSet.Put( SvxPostureItem( nVal != 0 ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC_CJK ) );
5588 rSet.Put( SvxPostureItem( nVal != 0 ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC_CTL ) );
5589 }
5590 if ( GetAttrib( PPT_CharAttr_Underline, nVal, nDestinationInstance ) )
5591 rSet.Put( SvxUnderlineItem( nVal != 0 ? LINESTYLE_SINGLE : LINESTYLE_NONE, EE_CHAR_UNDERLINE ) );
5592
5593 if ( GetAttrib( PPT_CharAttr_Shadow, nVal, nDestinationInstance ) )
5594 rSet.Put( SvxShadowedItem( nVal != 0, EE_CHAR_SHADOW ) );
5595
5596 if ( GetAttrib( PPT_CharAttr_Strikeout, nVal, nDestinationInstance ) )
5597 rSet.Put( SvxCrossedOutItem( nVal != 0 ? STRIKEOUT_SINGLE : STRIKEOUT_NONE, EE_CHAR_STRIKEOUT ) );
5598
5599 sal_uInt32 nAsianFontId = 0xffff;
5600 if ( GetAttrib( PPT_CharAttr_AsianOrComplexFont, nAsianFontId, nDestinationInstance ) )
5601 {
5602 if ( nAsianFontId != 0xffff )
5603 {
5604 PptFontEntityAtom* pFontEnityAtom = rManager.GetFontEnityAtom( nAsianFontId );
5605 if ( pFontEnityAtom )
5606 {
5607 rSet.Put( SvxFontItem( pFontEnityAtom->eFamily, pFontEnityAtom->aName,
5608 OUString(), pFontEnityAtom->ePitch, pFontEnityAtom->eCharSet, EE_CHAR_FONTINFO_CJK ) );
5609 rSet.Put( SvxFontItem( pFontEnityAtom->eFamily, pFontEnityAtom->aName,
5610 OUString(), pFontEnityAtom->ePitch, pFontEnityAtom->eCharSet, EE_CHAR_FONTINFO_CTL ) );
5611 }
5612 }
5613 }
5614 if ( GetAttrib( PPT_CharAttr_Font, nVal, nDestinationInstance ) )
5615 {
5616 PptFontEntityAtom* pFontEnityAtom = rManager.GetFontEnityAtom( nVal );
5617 if ( pFontEnityAtom )
5618 {
5619 rSet.Put( SvxFontItem( pFontEnityAtom->eFamily, pFontEnityAtom->aName, OUString(), pFontEnityAtom->ePitch, pFontEnityAtom->eCharSet, EE_CHAR_FONTINFO ) );
5620
5621 // #i119475# bullet font info for CJK and CTL
5622 if ( RTL_TEXTENCODING_SYMBOL == pFontEnityAtom->eCharSet )
5623 {
5624 rSet.Put( SvxFontItem( pFontEnityAtom->eFamily, pFontEnityAtom->aName, OUString(), pFontEnityAtom->ePitch, pFontEnityAtom->eCharSet, EE_CHAR_FONTINFO_CJK ) );
5625 rSet.Put( SvxFontItem( pFontEnityAtom->eFamily, pFontEnityAtom->aName, OUString(), pFontEnityAtom->ePitch, pFontEnityAtom->eCharSet, EE_CHAR_FONTINFO_CTL ) );
5626 }
5627 }
5628 }
5629 if ( GetAttrib( PPT_CharAttr_FontHeight, nVal, nDestinationInstance ) ) // Schriftgrad in Point
5630 {
5631 sal_uInt32 nHeight = rManager.ScalePoint( nVal );
5632 rSet.Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
5633 rSet.Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
5634 rSet.Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
5635 }
5636
5637 if ( GetAttrib( PPT_CharAttr_Embossed, nVal, nDestinationInstance ) )
5638 rSet.Put( SvxCharReliefItem( nVal != 0 ? FontRelief::Embossed : FontRelief::NONE, EE_CHAR_RELIEF ) );
5639 if ( nVal ) /* if Embossed is set, the font color depends to the fillstyle/color of the object,
5640 if the object has no fillstyle, the font color depends to fillstyle of the background */
5641 {
5642 Color aDefColor( COL_BLACK );
5643 sal_uInt32 eFillType = mso_fillSolid;
5644 if ( rManager.GetPropertyValue( DFF_Prop_fNoFillHitTest, 0 ) & 0x10 )
5645 eFillType = rManager.GetPropertyValue(DFF_Prop_fillType, mso_fillSolid);
5646 else
5647 eFillType = mso_fillBackground;
5648 switch( eFillType )
5649 {
5650 case mso_fillShade :
5651 case mso_fillShadeCenter :
5652 case mso_fillShadeShape :
5653 case mso_fillShadeScale :
5654 case mso_fillShadeTitle :
5655 case mso_fillSolid :
5656 aDefColor = rManager.MSO_CLR_ToColor( rManager.GetPropertyValue( DFF_Prop_fillColor, 0 ) );
5657 break;
5658 case mso_fillPattern :
5659 aDefColor = rManager.MSO_CLR_ToColor( rManager.GetPropertyValue( DFF_Prop_fillBackColor, 0 ) );
5660 break;
5661 case mso_fillTexture :
5662 {
5663 Graphic aGraf;
5664 if ( rManager.GetBLIP( rManager.GetPropertyValue( DFF_Prop_fillBlip, 0 ), aGraf ) )
5665 {
5666 Bitmap aBmp( aGraf.GetBitmapEx().GetBitmap() );
5667 Size aSize( aBmp.GetSizePixel() );
5668 if ( aSize.Width() && aSize.Height() )
5669 {
5670 if ( aSize.Width () > 64 )
5671 aSize.setWidth( 64 );
5672 if ( aSize.Height() > 64 )
5673 aSize.setHeight( 64 );
5674
5675 Bitmap::ScopedReadAccess pAcc(aBmp);
5676 if( pAcc )
5677 {
5678 sal_uLong nRt = 0, nGn = 0, nBl = 0;
5679 const tools::Long nWidth = aSize.Width();
5680 const tools::Long nHeight = aSize.Height();
5681
5682 if( pAcc->HasPalette() )
5683 {
5684 for( tools::Long nY = 0; nY < nHeight; nY++ )
5685 {
5686 Scanline pScanline = pAcc->GetScanline( nY );
5687 for( tools::Long nX = 0; nX < nWidth; nX++ )
5688 {
5689 const BitmapColor& rCol = pAcc->GetPaletteColor( pAcc->GetIndexFromData( pScanline, nX ) );
5690 nRt+=rCol.GetRed(); nGn+=rCol.GetGreen(); nBl+=rCol.GetBlue();
5691 }
5692 }
5693 }
5694 else
5695 {
5696 for( tools::Long nY = 0; nY < nHeight; nY++ )
5697 {
5698 Scanline pScanline = pAcc->GetScanline( nY );
5699 for( tools::Long nX = 0; nX < nWidth; nX++ )
5700 {
5701 const BitmapColor aCol( pAcc->GetPixelFromData( pScanline, nX ) );
5702 nRt+=aCol.GetRed(); nGn+=aCol.GetGreen(); nBl+=aCol.GetBlue();
5703 }
5704 }
5705 }
5706 pAcc.reset();
5707 sal_uInt32 nC = aSize.Width() * aSize.Height();
5708 nRt /= nC;
5709 nGn /= nC;
5710 nBl /= nC;
5711 aDefColor = Color(sal_uInt8( nRt ), sal_uInt8( nGn ),sal_uInt8( nBl ) );
5712 }
5713 }
5714 }
5715 }
5716 break;
5717 case mso_fillBackground :
5718 {
5719 if ( pTextObj ) // the textobject is needed
5720 {
5721 const SfxItemSet* pItemSet = pTextObj->GetBackground();
5722 if ( pItemSet )
5723 {
5724 const SfxPoolItem* pFillStyleItem = nullptr;
5725 pItemSet->GetItemState( XATTR_FILLSTYLE, false, &pFillStyleItem );
5726 if ( pFillStyleItem )
5727 {
5728 drawing::FillStyle eFillStyle = static_cast<const XFillStyleItem*>(pFillStyleItem)->GetValue();
5729 switch( eFillStyle )
5730 {
5731 case drawing::FillStyle_SOLID :
5732 {
5733 const SfxPoolItem* pFillColorItem = nullptr;
5734 pItemSet->GetItemState( XATTR_FILLCOLOR, false, &pFillColorItem );
5735 if ( pFillColorItem )
5736 aDefColor = static_cast<const XColorItem*>(pFillColorItem)->GetColorValue();
5737 }
5738 break;
5739 case drawing::FillStyle_GRADIENT :
5740 {
5741 const SfxPoolItem* pGradientItem = nullptr;
5742 pItemSet->GetItemState( XATTR_FILLGRADIENT, false, &pGradientItem );
5743 if ( pGradientItem )
5744 aDefColor = static_cast<const XFillGradientItem*>(pGradientItem)->GetGradientValue().GetStartColor();
5745 }
5746 break;
5747 case drawing::FillStyle_HATCH :
5748 case drawing::FillStyle_BITMAP :
5749 aDefColor = COL_WHITE;
5750 break;
5751 default: break;
5752 }
5753 }
5754 }
5755 }
5756 }
5757 break;
5758 default: break;
5759 }
5760 rSet.Put( SvxColorItem( aDefColor, EE_CHAR_COLOR ) );
5761 }
5762 else
5763 {
5764 if ( GetAttrib( PPT_CharAttr_FontColor, nVal, nDestinationInstance ) ) // text color (4Byte-Arg)
5765 {
5766 Color aCol( rManager.MSO_TEXT_CLR_ToColor( nVal ) );
5767 rSet.Put( SvxColorItem( aCol, EE_CHAR_COLOR ) );
5768 if ( nDestinationInstance == TSS_Type::Unknown )
5769 mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[ mnDepth ].mnFontColorInStyleSheet = aCol;
5770 }
5771 else if ( nVal & 0x0f000000 ) // this is not a hard attribute, but maybe the page has a different colorscheme,
5772 { // so that in this case we must use a hard color attribute
5773 Color aCol( rManager.MSO_TEXT_CLR_ToColor( nVal ) );
5774 Color& aColorInSheet = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[ mnDepth ].mnFontColorInStyleSheet;
5775 if ( aColorInSheet != aCol )
5776 rSet.Put( SvxColorItem( aCol, EE_CHAR_COLOR ) );
5777 }
5778 }
5779
5780 if ( GetAttrib( PPT_CharAttr_Escapement, nVal, nDestinationInstance ) ) // super-/subscript in %
5781 {
5782 sal_uInt16 nEsc = 0;
5783 sal_uInt8 nProp = 100;
5784
5785 if ( nVal )
5786 {
5787 nEsc = static_cast<sal_Int16>(nVal);
5788 nProp = DFLT_ESC_PROP;
5789 }
5790 SvxEscapementItem aItem( nEsc, nProp, EE_CHAR_ESCAPEMENT );
5791 rSet.Put( aItem );
5792 }
5793 if ( mnLanguage[ 0 ] )
5794 rSet.Put( SvxLanguageItem( mnLanguage[ 0 ], EE_CHAR_LANGUAGE ) );
5795 if ( mnLanguage[ 1 ] )
5796 rSet.Put( SvxLanguageItem( mnLanguage[ 1 ], EE_CHAR_LANGUAGE_CJK ) );
5797 if ( mnLanguage[ 2 ] )
5798 rSet.Put( SvxLanguageItem( mnLanguage[ 2 ], EE_CHAR_LANGUAGE_CTL ) );
5799 }
5800
GetTextField()5801 SvxFieldItem* PPTPortionObj::GetTextField()
5802 {
5803 if ( mpFieldItem )
5804 return new SvxFieldItem( *mpFieldItem );
5805 return nullptr;
5806 }
5807
5808 namespace
5809 {
sanitizeForMaxPPTLevels(sal_uInt16 nDepth)5810 sal_uInt16 sanitizeForMaxPPTLevels(sal_uInt16 nDepth)
5811 {
5812 if (nDepth >= nMaxPPTLevels)
5813 {
5814 SAL_WARN("filter.ms", "Para Style Sheet depth " << nDepth << " but " << nMaxPPTLevels - 1 << " is max possible");
5815 nDepth = nMaxPPTLevels - 1;
5816 }
5817 return nDepth;
5818 }
5819 }
5820
PPTParagraphObj(const PPTStyleSheet & rStyleSheet,TSS_Type nInstance,sal_uInt16 nDepth)5821 PPTParagraphObj::PPTParagraphObj( const PPTStyleSheet& rStyleSheet, TSS_Type nInstance, sal_uInt16 nDepth ) :
5822 PPTNumberFormatCreator ( nullptr ),
5823 mrStyleSheet ( rStyleSheet ),
5824 mnInstance ( nInstance ),
5825 mnCurrentObject ( 0 )
5826 {
5827 mxParaSet->mnDepth = sanitizeForMaxPPTLevels(nDepth);
5828 }
5829
PPTParagraphObj(PPTStyleTextPropReader & rPropReader,size_t const nCurParaPos,size_t & rnCurCharPos,const PPTStyleSheet & rStyleSheet,TSS_Type nInstance,PPTTextRulerInterpreter const & rRuler)5830 PPTParagraphObj::PPTParagraphObj( PPTStyleTextPropReader& rPropReader,
5831 size_t const nCurParaPos, size_t& rnCurCharPos,
5832 const PPTStyleSheet& rStyleSheet,
5833 TSS_Type nInstance, PPTTextRulerInterpreter const & rRuler ) :
5834 PPTParaPropSet ( *rPropReader.aParaPropList[nCurParaPos] ),
5835 PPTNumberFormatCreator ( nullptr ),
5836 PPTTextRulerInterpreter ( rRuler ),
5837 mrStyleSheet ( rStyleSheet ),
5838 mnInstance ( nInstance ),
5839 mnCurrentObject ( 0 )
5840 {
5841 if (rnCurCharPos >= rPropReader.aCharPropList.size())
5842 return;
5843
5844 sal_uInt32 const nCurrentParagraph =
5845 rPropReader.aCharPropList[rnCurCharPos]->mnParagraph;
5846 for (; rnCurCharPos < rPropReader.aCharPropList.size() &&
5847 rPropReader.aCharPropList[rnCurCharPos]->mnParagraph == nCurrentParagraph;
5848 ++rnCurCharPos)
5849 {
5850 PPTCharPropSet *const pCharPropSet =
5851 rPropReader.aCharPropList[rnCurCharPos].get();
5852 std::unique_ptr<PPTPortionObj> pPPTPortion(new PPTPortionObj(
5853 *pCharPropSet, rStyleSheet, nInstance, mxParaSet->mnDepth));
5854 m_PortionList.push_back(std::move(pPPTPortion));
5855 }
5856 }
5857
~PPTParagraphObj()5858 PPTParagraphObj::~PPTParagraphObj()
5859 {
5860 }
5861
AppendPortion(PPTPortionObj & rPPTPortion)5862 void PPTParagraphObj::AppendPortion( PPTPortionObj& rPPTPortion )
5863 {
5864 m_PortionList.push_back(
5865 std::make_unique<PPTPortionObj>(rPPTPortion));
5866 }
5867
UpdateBulletRelSize(sal_uInt32 & nBulletRelSize) const5868 void PPTParagraphObj::UpdateBulletRelSize( sal_uInt32& nBulletRelSize ) const
5869 {
5870 if ( nBulletRelSize <= 0x7fff ) // a negative value is the absolute bullet height
5871 return;
5872
5873 sal_uInt16 nFontHeight = 0;
5874 if (!m_PortionList.empty())
5875 {
5876 PPTPortionObj const& rPortion = *m_PortionList.front();
5877 if (rPortion.mpImplPPTCharPropSet->mnAttrSet & (1 << PPT_CharAttr_FontHeight))
5878 {
5879 nFontHeight = rPortion.mpImplPPTCharPropSet->mnFontHeight;
5880 }
5881 }
5882 // if we do not have a hard attributed fontheight, the fontheight is taken from the style
5883 if ( !nFontHeight )
5884 {
5885 nFontHeight = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[sanitizeForMaxPPTLevels(mxParaSet->mnDepth)].mnFontHeight;
5886 }
5887 nBulletRelSize = nFontHeight ? ((- static_cast<sal_Int16>(nBulletRelSize)) * 100 ) / nFontHeight : 100;
5888 }
5889
GetAttrib(sal_uInt32 nAttr,sal_uInt32 & rRetValue,TSS_Type nDestinationInstance)5890 bool PPTParagraphObj::GetAttrib( sal_uInt32 nAttr, sal_uInt32& rRetValue, TSS_Type nDestinationInstance )
5891 {
5892 sal_uInt32 nMask = 1 << nAttr;
5893 rRetValue = 0;
5894
5895 if ( nAttr > 21 )
5896 {
5897 OSL_FAIL( "SJ:PPTParagraphObj::GetAttrib - attribute does not exist" );
5898 return false;
5899 }
5900
5901 bool bIsHardAttribute = ( ( mxParaSet->mnAttrSet & nMask ) != 0 );
5902
5903 sal_uInt16 nDepth = sanitizeForMaxPPTLevels(mxParaSet->mnDepth);
5904
5905 if ( bIsHardAttribute )
5906 {
5907 if ( nAttr == PPT_ParaAttr_BulletColor )
5908 {
5909 bool bHardBulletColor;
5910 if ( mxParaSet->mnAttrSet & ( 1 << PPT_ParaAttr_BuHardColor ) )
5911 bHardBulletColor = mxParaSet->mpArry[ PPT_ParaAttr_BuHardColor ] != 0;
5912 else
5913 bHardBulletColor = ( mrStyleSheet.mpParaSheet[ mnInstance ]->maParaLevel[nDepth].mnBuFlags
5914 & ( 1 << PPT_ParaAttr_BuHardColor ) ) != 0;
5915 if ( bHardBulletColor )
5916 rRetValue = mxParaSet->mnBulletColor;
5917 else
5918 {
5919 rRetValue = PPT_COLSCHEME_TEXT_UND_ZEILEN;
5920 if ((nDestinationInstance != TSS_Type::Unknown) && !m_PortionList.empty())
5921 {
5922 PPTPortionObj const& rPortion = *m_PortionList.front();
5923 if (rPortion.mpImplPPTCharPropSet->mnAttrSet & (1 << PPT_CharAttr_FontColor))
5924 {
5925 rRetValue = rPortion.mpImplPPTCharPropSet->mnColor;
5926 }
5927 else
5928 {
5929 rRetValue = mrStyleSheet.mpCharSheet[ nDestinationInstance ]->maCharLevel[nDepth].mnFontColor;
5930 }
5931 }
5932 }
5933 }
5934 else if ( nAttr == PPT_ParaAttr_BulletFont )
5935 {
5936 bool bHardBuFont;
5937 if ( mxParaSet->mnAttrSet & ( 1 << PPT_ParaAttr_BuHardFont ) )
5938 bHardBuFont = mxParaSet->mpArry[ PPT_ParaAttr_BuHardFont ] != 0;
5939 else
5940 bHardBuFont = ( mrStyleSheet.mpParaSheet[ mnInstance ]->maParaLevel[nDepth].mnBuFlags
5941 & ( 1 << PPT_ParaAttr_BuHardFont ) ) != 0;
5942 if ( bHardBuFont )
5943 rRetValue = mxParaSet->mpArry[ PPT_ParaAttr_BulletFont ];
5944 else
5945 {
5946 // it is the font used which assigned to the first character of the following text
5947 rRetValue = 0;
5948 if ((nDestinationInstance != TSS_Type::Unknown) && !m_PortionList.empty())
5949 {
5950 PPTPortionObj const& rPortion = *m_PortionList.front();
5951 if (rPortion.mpImplPPTCharPropSet->mnAttrSet & ( 1 << PPT_CharAttr_Font ) )
5952 {
5953 rRetValue = rPortion.mpImplPPTCharPropSet->mnFont;
5954 }
5955 else
5956 {
5957 rRetValue = mrStyleSheet.mpCharSheet[ nDestinationInstance ]->maCharLevel[nDepth].mnFont;
5958 }
5959 }
5960 }
5961 }
5962 else
5963 rRetValue = mxParaSet->mpArry[ nAttr ];
5964 }
5965 else
5966 {
5967 const PPTParaLevel& rParaLevel = mrStyleSheet.mpParaSheet[ mnInstance ]->maParaLevel[nDepth];
5968
5969 PPTParaLevel* pParaLevel = nullptr;
5970 if ( ( nDestinationInstance == TSS_Type::Unknown )
5971 || ( nDepth && ( ( mnInstance == TSS_Type::Subtitle ) || ( mnInstance == TSS_Type::TextInShape ) ) ) )
5972 bIsHardAttribute = true;
5973 else if ( nDestinationInstance != mnInstance )
5974 pParaLevel = &mrStyleSheet.mpParaSheet[ nDestinationInstance ]->maParaLevel[nDepth];
5975 switch ( nAttr )
5976 {
5977 case PPT_ParaAttr_BulletOn :
5978 {
5979 rRetValue = rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BulletOn );
5980 if ( pParaLevel )
5981 {
5982 if ( rRetValue != ( static_cast<sal_uInt32>(pParaLevel->mnBuFlags) & ( 1 << PPT_ParaAttr_BulletOn ) ) )
5983 bIsHardAttribute = true;
5984 }
5985 }
5986 break;
5987 case PPT_ParaAttr_BuHardFont :
5988 case PPT_ParaAttr_BuHardColor :
5989 case PPT_ParaAttr_BuHardHeight :
5990 OSL_FAIL( "SJ:PPTParagraphObj::GetAttrib - this attribute does not make sense" );
5991 break;
5992 case PPT_ParaAttr_BulletChar :
5993 {
5994 rRetValue = rParaLevel.mnBulletChar;
5995 if ( pParaLevel && ( rRetValue != pParaLevel->mnBulletChar ) )
5996 bIsHardAttribute = true;
5997 }
5998 break;
5999 case PPT_ParaAttr_BulletFont :
6000 {
6001 bool bHardBuFont;
6002 if ( mxParaSet->mnAttrSet & ( 1 << PPT_ParaAttr_BuHardFont ) )
6003 bHardBuFont = mxParaSet->mpArry[ PPT_ParaAttr_BuHardFont ] != 0;
6004 else
6005 bHardBuFont = ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BuHardFont ) ) != 0;
6006 if ( bHardBuFont )
6007 {
6008 rRetValue = rParaLevel.mnBulletFont;
6009 if ( pParaLevel && ( rRetValue != pParaLevel->mnBulletFont ) )
6010 bIsHardAttribute = true;
6011 }
6012 else
6013 {
6014 if (!m_PortionList.empty())
6015 {
6016 PPTPortionObj const& rPortion = *m_PortionList.front();
6017 bIsHardAttribute = rPortion.GetAttrib(
6018 PPT_CharAttr_Font, rRetValue, nDestinationInstance);
6019 }
6020 else
6021 {
6022 rRetValue = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[nDepth].mnFont;
6023 bIsHardAttribute = true;
6024 }
6025 }
6026 }
6027 break;
6028 case PPT_ParaAttr_BulletHeight :
6029 {
6030 rRetValue = rParaLevel.mnBulletHeight;
6031 if ( pParaLevel && ( rRetValue != pParaLevel->mnBulletHeight ) )
6032 bIsHardAttribute = true;
6033 }
6034 break;
6035 case PPT_ParaAttr_BulletColor :
6036 {
6037 bool bHardBulletColor;
6038 if ( mxParaSet->mnAttrSet & ( 1 << PPT_ParaAttr_BuHardColor ) )
6039 bHardBulletColor = mxParaSet->mpArry[ PPT_ParaAttr_BuHardColor ] != 0;
6040 else
6041 bHardBulletColor = ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BuHardColor ) ) != 0;
6042 if ( bHardBulletColor )
6043 {
6044 rRetValue = rParaLevel.mnBulletColor;
6045 if ( pParaLevel && ( rRetValue != pParaLevel->mnBulletColor ) )
6046 bIsHardAttribute = true;
6047 }
6048 else
6049 {
6050 if (!m_PortionList.empty())
6051 {
6052 PPTPortionObj const& rPortion = *m_PortionList.front();
6053 if (rPortion.mbIsHyperlink )
6054 {
6055 if( rPortion.mbHardHylinkOrigColor )
6056 rRetValue = rPortion.mnHylinkOrigColor;
6057 else
6058 rRetValue = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[nDepth].mnFontColor;
6059 bIsHardAttribute = true;
6060 }
6061 else
6062 {
6063 bIsHardAttribute = rPortion.GetAttrib( PPT_CharAttr_FontColor, rRetValue, nDestinationInstance );
6064 }
6065 }
6066 else
6067 {
6068 rRetValue = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[nDepth].mnFontColor;
6069 bIsHardAttribute = true;
6070 }
6071 }
6072 }
6073 break;
6074 case PPT_ParaAttr_Adjust :
6075 {
6076 rRetValue = rParaLevel.mnAdjust;
6077 if ( pParaLevel && ( rRetValue != pParaLevel->mnAdjust ) )
6078 bIsHardAttribute = true;
6079 }
6080 break;
6081 case PPT_ParaAttr_LineFeed :
6082 {
6083 rRetValue = rParaLevel.mnLineFeed;
6084 if ( pParaLevel && ( rRetValue != pParaLevel->mnLineFeed ) )
6085 bIsHardAttribute = true;
6086 }
6087 break;
6088 case PPT_ParaAttr_UpperDist :
6089 {
6090 rRetValue = rParaLevel.mnUpperDist;
6091 if ( pParaLevel && ( rRetValue != pParaLevel->mnUpperDist ) )
6092 bIsHardAttribute = true;
6093 }
6094 break;
6095 case PPT_ParaAttr_LowerDist :
6096 {
6097 rRetValue = rParaLevel.mnLowerDist;
6098 if ( pParaLevel && ( rRetValue != pParaLevel->mnLowerDist ) )
6099 bIsHardAttribute = true;
6100 }
6101 break;
6102 case PPT_ParaAttr_TextOfs :
6103 {
6104 rRetValue = rParaLevel.mnTextOfs;
6105 if ( pParaLevel && ( rRetValue != pParaLevel->mnTextOfs ) )
6106 bIsHardAttribute = true;
6107 }
6108 break;
6109 case PPT_ParaAttr_BulletOfs :
6110 {
6111 rRetValue = rParaLevel.mnBulletOfs;
6112 if ( pParaLevel && ( rRetValue != pParaLevel->mnBulletOfs ) )
6113 bIsHardAttribute = true;
6114 }
6115 break;
6116 case PPT_ParaAttr_DefaultTab :
6117 {
6118 rRetValue = rParaLevel.mnDefaultTab;
6119 if ( pParaLevel && ( rRetValue != pParaLevel->mnDefaultTab ) )
6120 bIsHardAttribute = true;
6121 }
6122 break;
6123 case PPT_ParaAttr_AsianLB_1 :
6124 {
6125 rRetValue = rParaLevel.mnAsianLineBreak & 1;
6126 if ( pParaLevel && ( rRetValue != ( static_cast<sal_uInt32>(pParaLevel->mnAsianLineBreak) & 1 ) ) )
6127 bIsHardAttribute = true;
6128 }
6129 break;
6130 case PPT_ParaAttr_AsianLB_2 :
6131 {
6132 rRetValue = ( rParaLevel.mnAsianLineBreak >> 1 ) & 1;
6133 if ( pParaLevel && ( rRetValue != ( ( static_cast<sal_uInt32>(pParaLevel->mnAsianLineBreak) >> 1 ) & 1 ) ) )
6134 bIsHardAttribute = true;
6135 }
6136 break;
6137 case PPT_ParaAttr_AsianLB_3 :
6138 {
6139 rRetValue = ( rParaLevel.mnAsianLineBreak >> 2 ) & 1;
6140 if ( pParaLevel && ( rRetValue != ( ( static_cast<sal_uInt32>(pParaLevel->mnAsianLineBreak) >> 2 ) & 1 ) ) )
6141 bIsHardAttribute = true;
6142 }
6143 break;
6144 case PPT_ParaAttr_BiDi :
6145 {
6146 rRetValue = rParaLevel.mnBiDi;
6147 if ( pParaLevel && ( rRetValue != pParaLevel->mnBiDi ) )
6148 bIsHardAttribute = true;
6149 }
6150 break;
6151 }
6152 }
6153 return bIsHardAttribute;
6154 }
6155
ApplyTo(SfxItemSet & rSet,std::optional<sal_Int16> & rStartNumbering,SdrPowerPointImport const & rManager,TSS_Type nDestinationInstance)6156 void PPTParagraphObj::ApplyTo( SfxItemSet& rSet, std::optional< sal_Int16 >& rStartNumbering, SdrPowerPointImport const & rManager, TSS_Type nDestinationInstance )
6157 {
6158 sal_Int16 nVal2;
6159 sal_uInt32 nVal, nUpperDist, nLowerDist;
6160 TSS_Type nInstance = nDestinationInstance != TSS_Type::Unknown ? nDestinationInstance : mnInstance;
6161
6162 if ( ( nDestinationInstance != TSS_Type::Unknown ) || ( mxParaSet->mnDepth <= 1 ) )
6163 {
6164 SvxNumBulletItem* pNumBulletItem = mrStyleSheet.mpNumBulletItem[ nInstance ].get();
6165 if ( pNumBulletItem )
6166 {
6167 SvxNumberFormat aNumberFormat( SVX_NUM_NUMBER_NONE );
6168 if ( GetNumberFormat( rManager, aNumberFormat, this, nDestinationInstance, rStartNumbering ) )
6169 {
6170 if ( aNumberFormat.GetNumberingType() == SVX_NUM_NUMBER_NONE )
6171 {
6172 aNumberFormat.SetAbsLSpace( 0 );
6173 aNumberFormat.SetFirstLineOffset( 0 );
6174 aNumberFormat.SetCharTextDistance( 0 );
6175 aNumberFormat.SetFirstLineIndent( 0 );
6176 aNumberFormat.SetIndentAt( 0 );
6177 }
6178 SvxNumBulletItem aNewNumBulletItem( *pNumBulletItem );
6179 SvxNumRule& rRule = aNewNumBulletItem.GetNumRule();
6180 rRule.SetLevel( mxParaSet->mnDepth, aNumberFormat );
6181 for (sal_uInt16 i = 0; i < rRule.GetLevelCount(); ++i)
6182 {
6183 if ( i != mxParaSet->mnDepth )
6184 {
6185 sal_uInt16 n = sanitizeForMaxPPTLevels(i);
6186
6187 SvxNumberFormat aNumberFormat2( rRule.GetLevel( i ) );
6188 const PPTParaLevel& rParaLevel = mrStyleSheet.mpParaSheet[ nInstance ]->maParaLevel[ n ];
6189 const PPTCharLevel& rCharLevel = mrStyleSheet.mpCharSheet[ nInstance ]->maCharLevel[ n ];
6190 sal_uInt32 nColor;
6191 if ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BuHardColor ) )
6192 nColor = rParaLevel.mnBulletColor;
6193 else
6194 nColor = rCharLevel.mnFontColor;
6195 aNumberFormat2.SetBulletColor( rManager.MSO_TEXT_CLR_ToColor( nColor ) );
6196 rRule.SetLevel( i, aNumberFormat2 );
6197 }
6198 }
6199 rSet.Put( aNewNumBulletItem );
6200 }
6201 }
6202 }
6203
6204 sal_uInt32 nIsBullet2, _nTextOfs, _nBulletOfs;
6205 GetAttrib(PPT_ParaAttr_BulletOn, nIsBullet2, nDestinationInstance);
6206 GetAttrib(PPT_ParaAttr_TextOfs, _nTextOfs, nDestinationInstance);
6207 GetAttrib(PPT_ParaAttr_BulletOfs, _nBulletOfs, nDestinationInstance);
6208 if ( !nIsBullet2 )
6209 {
6210 SvxLRSpaceItem aLRSpaceItem( EE_PARA_LRSPACE );
6211 auto const nAbsLSpace = convertMasterUnitToMm100(_nTextOfs);
6212 auto const nFirstLineOffset = nAbsLSpace - convertMasterUnitToMm100(_nBulletOfs);
6213 aLRSpaceItem.SetLeft( nAbsLSpace );
6214 aLRSpaceItem.SetTextFirstLineOffsetValue( -nFirstLineOffset );
6215 rSet.Put( aLRSpaceItem );
6216 }
6217 else
6218 {
6219 SvxLRSpaceItem aLRSpaceItem( EE_PARA_LRSPACE );
6220 aLRSpaceItem.SetLeft( 0 );
6221 aLRSpaceItem.SetTextFirstLineOffsetValue( 0 );
6222 rSet.Put( aLRSpaceItem );
6223 }
6224 if ( GetAttrib( PPT_ParaAttr_Adjust, nVal, nDestinationInstance ) )
6225 {
6226 if ( nVal <= 3 )
6227 { // paragraph adjustment
6228 static SvxAdjust const aAdj[ 4 ] = { SvxAdjust::Left, SvxAdjust::Center, SvxAdjust::Right, SvxAdjust::Block };
6229 rSet.Put( SvxAdjustItem( aAdj[ nVal ], EE_PARA_JUST ) );
6230 }
6231 }
6232
6233 if ( GetAttrib( PPT_ParaAttr_AsianLB_1, nVal, nDestinationInstance ) )
6234 rSet.Put(SvxForbiddenRuleItem(nVal != 0, EE_PARA_FORBIDDENRULES));
6235 if ( GetAttrib( PPT_ParaAttr_AsianLB_3, nVal, nDestinationInstance ) )
6236 rSet.Put(SvxHangingPunctuationItem(nVal != 0, EE_PARA_HANGINGPUNCTUATION));
6237
6238 if ( GetAttrib( PPT_ParaAttr_BiDi, nVal, nDestinationInstance ) )
6239 rSet.Put( SvxFrameDirectionItem( nVal == 1 ? SvxFrameDirection::Horizontal_RL_TB : SvxFrameDirection::Horizontal_LR_TB, EE_PARA_WRITINGDIR ) );
6240
6241 // LineSpacing
6242 PPTPortionObj* pPortion = First();
6243 bool bIsHardAttribute = GetAttrib( PPT_ParaAttr_LineFeed, nVal, nDestinationInstance );
6244 nVal2 = static_cast<sal_Int16>(nVal);
6245 sal_uInt32 nFont = sal_uInt32();
6246 if ( pPortion && pPortion->GetAttrib( PPT_CharAttr_Font, nFont, nDestinationInstance ) )
6247 bIsHardAttribute = true;
6248
6249 if ( bIsHardAttribute )
6250 {
6251 SdrTextFixedCellHeightItem aHeightItem(true);
6252 aHeightItem.SetWhich(SDRATTR_TEXT_USEFIXEDCELLHEIGHT);
6253 rSet.Put( aHeightItem );
6254 SvxLineSpacingItem aItem( 200, EE_PARA_SBL );
6255 if ( nVal2 <= 0 ) {
6256 aItem.SetLineHeight( static_cast<sal_uInt16>( rManager.ScalePoint( -nVal2 ) / 8 ) );
6257 aItem.SetLineSpaceRule( SvxLineSpaceRule::Fix );
6258 aItem.SetInterLineSpaceRule(SvxInterLineSpaceRule::Off);
6259 } else
6260 {
6261 sal_uInt16 nPropLineSpace = static_cast<sal_uInt16>(nVal2);
6262 aItem.SetPropLineSpace( nPropLineSpace );
6263 aItem.SetLineSpaceRule( SvxLineSpaceRule::Auto );
6264 }
6265 rSet.Put( aItem );
6266 }
6267
6268 // Paragraph Spacing
6269 bIsHardAttribute = ( static_cast<sal_uInt32>(GetAttrib( PPT_ParaAttr_UpperDist, nUpperDist, nDestinationInstance )) +
6270 static_cast<sal_uInt32>(GetAttrib( PPT_ParaAttr_LowerDist, nLowerDist, nDestinationInstance )) ) != 0;
6271 if ( ( nUpperDist > 0 ) || ( nLowerDist > 0 ) )
6272 {
6273 if (!m_PortionList.empty())
6274 {
6275 sal_uInt32 nFontHeight = 0;
6276 m_PortionList.back()->GetAttrib(
6277 PPT_CharAttr_FontHeight, nFontHeight, nDestinationInstance);
6278 if ( static_cast<sal_Int16>(nUpperDist) > 0 )
6279 nUpperDist = - static_cast<sal_Int16>( ( nFontHeight * nUpperDist * 100 ) / 1000 );
6280 if ( static_cast<sal_Int16>(nLowerDist) > 0 )
6281 nLowerDist = - static_cast<sal_Int16>( ( nFontHeight * nLowerDist * 100 ) / 1000 );
6282 }
6283 bIsHardAttribute = true;
6284 }
6285 if ( bIsHardAttribute )
6286 {
6287 SvxULSpaceItem aULSpaceItem( EE_PARA_ULSPACE );
6288 nVal2 = static_cast<sal_Int16>(nUpperDist);
6289 if ( nVal2 <= 0 )
6290 aULSpaceItem.SetUpper(static_cast<sal_uInt16>(convertMasterUnitToMm100(-nVal2)));
6291 else
6292 {
6293 aULSpaceItem.SetUpperValue( 0 );
6294 aULSpaceItem.SetPropUpper( static_cast<sal_uInt16>(nUpperDist) == 100 ? 101 : static_cast<sal_uInt16>(nUpperDist) );
6295 }
6296 nVal2 = static_cast<sal_Int16>(nLowerDist);
6297 if ( nVal2 <= 0 )
6298 aULSpaceItem.SetLower(static_cast<sal_uInt16>(convertMasterUnitToMm100(-nVal2)));
6299 else
6300 {
6301 aULSpaceItem.SetLowerValue( 0 );
6302 aULSpaceItem.SetPropLower( static_cast<sal_uInt16>(nLowerDist) == 100 ? 101 : static_cast<sal_uInt16>(nLowerDist) );
6303 }
6304 rSet.Put( aULSpaceItem );
6305 }
6306
6307 sal_uInt32 i, nDefaultTab, nTab, nTextOfs2 = 0;
6308 sal_uInt32 nLatestManTab = 0;
6309 GetAttrib( PPT_ParaAttr_TextOfs, nTextOfs2, nDestinationInstance );
6310 GetAttrib( PPT_ParaAttr_BulletOfs, nTab, nDestinationInstance );
6311 GetAttrib( PPT_ParaAttr_DefaultTab, nDefaultTab, nDestinationInstance );
6312
6313 SvxTabStopItem aTabItem( 0, 0, SvxTabAdjust::Default, EE_PARA_TABS );
6314 if ( GetTabCount() )
6315 {
6316 for ( i = 0; i < GetTabCount(); i++ )
6317 {
6318 SvxTabAdjust eTabAdjust;
6319 nTab = GetTabOffsetByIndex( static_cast<sal_uInt16>(i) );
6320 switch( GetTabStyleByIndex( static_cast<sal_uInt16>(i) ) )
6321 {
6322 case 1 : eTabAdjust = SvxTabAdjust::Center; break;
6323 case 2 : eTabAdjust = SvxTabAdjust::Right; break;
6324 case 3 : eTabAdjust = SvxTabAdjust::Decimal; break;
6325 default : eTabAdjust = SvxTabAdjust::Left;
6326 }
6327 aTabItem.Insert(SvxTabStop(convertMasterUnitToMm100(nTab), eTabAdjust));
6328 }
6329 nLatestManTab = nTab;
6330 }
6331 if ( nIsBullet2 == 0 )
6332 aTabItem.Insert( SvxTabStop( sal_uInt16(0) ) );
6333 if ( nDefaultTab )
6334 {
6335 nTab = std::max( nTextOfs2, nLatestManTab );
6336 nTab /= nDefaultTab;
6337 nTab = nDefaultTab * ( 1 + nTab );
6338 for ( i = 0; ( i < 20 ) && ( nTab < 0x1b00 ); i++ )
6339 {
6340 aTabItem.Insert( SvxTabStop( convertMasterUnitToMm100(nTab)));
6341 nTab += nDefaultTab;
6342 }
6343 }
6344 rSet.Put( aTabItem );
6345 }
6346
GetTextSize()6347 sal_uInt32 PPTParagraphObj::GetTextSize()
6348 {
6349 sal_uInt32 nCount, nRetValue = 0;
6350 for (const std::unique_ptr<PPTPortionObj> & i : m_PortionList)
6351 {
6352 PPTPortionObj const& rPortionObj = *i;
6353 nCount = rPortionObj.Count();
6354 if ((!nCount) && rPortionObj.mpFieldItem)
6355 nCount++;
6356 nRetValue += nCount;
6357 }
6358 return nRetValue;
6359 }
6360
First()6361 PPTPortionObj* PPTParagraphObj::First()
6362 {
6363 mnCurrentObject = 0;
6364 if (m_PortionList.empty())
6365 return nullptr;
6366 return m_PortionList.front().get();
6367 }
6368
Next()6369 PPTPortionObj* PPTParagraphObj::Next()
6370 {
6371 sal_uInt32 i = mnCurrentObject + 1;
6372 if (i >= m_PortionList.size())
6373 return nullptr;
6374 mnCurrentObject++;
6375 return m_PortionList[i].get();
6376 }
6377
~PPTFieldEntry()6378 PPTFieldEntry::~PPTFieldEntry()
6379 {
6380 }
6381
GetDateTime(const sal_uInt32 nVal,SvxDateFormat & eDateFormat,SvxTimeFormat & eTimeFormat)6382 void PPTFieldEntry::GetDateTime( const sal_uInt32 nVal, SvxDateFormat& eDateFormat, SvxTimeFormat& eTimeFormat )
6383 {
6384 eDateFormat = SvxDateFormat::AppDefault;
6385 eTimeFormat = SvxTimeFormat::AppDefault;
6386 // evaluate ID
6387 switch( nVal )
6388 {
6389 case 0:
6390 case 6:
6391 eDateFormat = SvxDateFormat::A;
6392 break;
6393 case 1:
6394 eDateFormat = SvxDateFormat::F;
6395 break;
6396 case 2:
6397 case 3:
6398 eDateFormat = SvxDateFormat::D;
6399 break;
6400 case 4:
6401 case 5:
6402 eDateFormat = SvxDateFormat::C;
6403 break;
6404 case 7:
6405 eDateFormat = SvxDateFormat::A;
6406 [[fallthrough]];
6407 case 9:
6408 eTimeFormat = SvxTimeFormat::HH24_MM;
6409 break;
6410 case 8:
6411 eDateFormat = SvxDateFormat::A;
6412 [[fallthrough]];
6413 case 11:
6414 eTimeFormat = SvxTimeFormat::HH12_MM;
6415 break;
6416 case 10:
6417 eTimeFormat = SvxTimeFormat::HH24_MM_SS;
6418 break;
6419 case 12:
6420 eTimeFormat = SvxTimeFormat::HH12_MM_SS;
6421 break;
6422 }
6423 }
6424
SetDateTime(sal_uInt32 nVal)6425 void PPTFieldEntry::SetDateTime( sal_uInt32 nVal )
6426 {
6427 SvxDateFormat eDateFormat;
6428 SvxTimeFormat eTimeFormat;
6429 GetDateTime( nVal, eDateFormat, eTimeFormat );
6430 if ( eDateFormat != SvxDateFormat::AppDefault )
6431 xField1.reset(new SvxFieldItem(SvxDateField( Date( Date::SYSTEM ), SvxDateType::Var, eDateFormat ), EE_FEATURE_FIELD));
6432 if ( eTimeFormat != SvxTimeFormat::AppDefault )
6433 {
6434 std::unique_ptr<SvxFieldItem> xFieldItem(new SvxFieldItem(SvxExtTimeField( tools::Time( tools::Time::SYSTEM ), SvxTimeType::Var, eTimeFormat ), EE_FEATURE_FIELD));
6435 if (xField1)
6436 xField2 = std::move(xFieldItem);
6437 else
6438 xField1 = std::move(xFieldItem);
6439 }
6440 }
6441
PPTTextObj(SvStream & rIn,SdrPowerPointImport & rSdrPowerPointImport,PptSlidePersistEntry & rPersistEntry,DffObjData const * pObjData)6442 PPTTextObj::PPTTextObj( SvStream& rIn, SdrPowerPointImport& rSdrPowerPointImport, PptSlidePersistEntry& rPersistEntry, DffObjData const * pObjData ) :
6443 mxImplTextObj ( new ImplPPTTextObj( rPersistEntry ) )
6444 {
6445 mxImplTextObj->mnShapeId = 0;
6446 mxImplTextObj->mnShapeMaster = 0;
6447 mxImplTextObj->mnDestinationInstance = mxImplTextObj->mnInstance = TSS_Type::TextInShape;
6448 mxImplTextObj->mnCurrentObject = 0;
6449 mxImplTextObj->mnParagraphCount = 0;
6450 mxImplTextObj->mnTextFlags = 0;
6451 mxImplTextObj->meShapeType = ( pObjData && pObjData->bShapeType ) ? pObjData->eShapeType : mso_sptMin;
6452
6453 DffRecordHeader aExtParaHd;
6454 aExtParaHd.nRecType = 0; // set empty
6455
6456
6457 DffRecordHeader aShapeContainerHd;
6458 ReadDffRecordHeader( rIn, aShapeContainerHd );
6459
6460 if ( !(( pObjData == nullptr ) || ( pObjData->bShapeType )) )
6461 return;
6462
6463 PPTExtParaProv* pExtParaProv = rSdrPowerPointImport.m_pPPTStyleSheet->pExtParaProv.get();
6464 if ( pObjData )
6465 {
6466 mxImplTextObj->mnShapeId = pObjData->nShapeId;
6467 if ( pObjData->nSpFlags & ShapeFlag::HaveMaster )
6468 mxImplTextObj->mnShapeMaster = rSdrPowerPointImport.GetPropertyValue( DFF_Prop_hspMaster, 0 );
6469 }
6470 // ClientData
6471 if ( rSdrPowerPointImport.maShapeRecords.SeekToContent( rIn, DFF_msofbtClientData, SEEK_FROM_CURRENT_AND_RESTART ) )
6472 {
6473 sal_uInt32 nOldPos = rIn.Tell();
6474 DffRecordHeader& aClientDataContainerHd = *rSdrPowerPointImport.maShapeRecords.Current();
6475 DffRecordHeader aPlaceHolderAtomHd;
6476 if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_OEPlaceholderAtom, aClientDataContainerHd.GetRecEndFilePos(), &aPlaceHolderAtomHd ) )
6477 {
6478 mxImplTextObj->mpPlaceHolderAtom.reset( new PptOEPlaceholderAtom );
6479 ReadPptOEPlaceholderAtom( rIn, *( mxImplTextObj->mpPlaceHolderAtom ) );
6480 }
6481 rIn.Seek( nOldPos );
6482 DffRecordHeader aProgTagHd;
6483 if ( SdrPowerPointImport::SeekToContentOfProgTag( 9, rIn, aClientDataContainerHd, aProgTagHd ) )
6484 {
6485 ReadDffRecordHeader( rIn, aExtParaHd );
6486 }
6487 }
6488
6489 // ClientTextBox
6490 if ( !rSdrPowerPointImport.maShapeRecords.SeekToContent( rIn, DFF_msofbtClientTextbox, SEEK_FROM_CURRENT_AND_RESTART ) )
6491 return;
6492
6493 bool bStatus = true;
6494
6495
6496 DffRecordHeader aClientTextBoxHd( *rSdrPowerPointImport.maShapeRecords.Current() );
6497 sal_uInt32 nTextRulerAtomOfs = 0; // case of zero -> this atom may be found in aClientDataContainerHd;
6498 // case of -1 -> there is no atom of this kind
6499 // else -> this is the fileofs where we can get it
6500
6501 // checkout if this is a referenced
6502 // textobj, if so the we will patch
6503 // the ClientTextBoxHd for a
6504 // equivalent one
6505 DffRecordHeader aTextHd;
6506 if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_OutlineTextRefAtom, aClientTextBoxHd.GetRecEndFilePos(), &aTextHd ) )
6507 {
6508 sal_uInt32 nRefNum;
6509 rIn.ReadUInt32( nRefNum );
6510
6511 if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_TextRulerAtom, aClientTextBoxHd.GetRecEndFilePos() ) )
6512 nTextRulerAtomOfs = rIn.Tell();
6513 else
6514 nTextRulerAtomOfs = 0xffffffff;
6515
6516 sal_uInt32 nInstance = 0;
6517 switch( rSdrPowerPointImport.m_eCurrentPageKind )
6518 {
6519 case PPT_NOTEPAGE :
6520 nInstance++;
6521 [[fallthrough]];
6522 case PPT_MASTERPAGE :
6523 nInstance++;
6524 break;
6525 case PPT_SLIDEPAGE :
6526 break;
6527 default :
6528 bStatus = false;
6529 }
6530 if ( bStatus )
6531 {
6532 sal_uInt32 nSlideId = rSdrPowerPointImport.GetCurrentPageId();
6533 if ( !nSlideId )
6534 bStatus = false;
6535 else
6536 {
6537 if ( !aExtParaHd.nRecType )
6538 {
6539 sal_uInt32 nOldPos = rIn.Tell();
6540 // try to locate the referenced ExtendedParaHd
6541 DffRecordHeader* pHd = pExtParaProv->
6542 aExtendedPresRules.GetRecordHeader( PPT_PST_ExtendedParagraphHeaderAtom,
6543 SEEK_FROM_CURRENT_AND_RESTART );
6544 DffRecordHeader aPresRuleHd;
6545 DffRecordHeader* pFirst = pHd;
6546
6547 sal_uInt32 nTmpSlideId, nTmpRef;
6548 while ( pHd )
6549 {
6550 pHd->SeekToContent( rIn );
6551 rIn.ReadUInt32( nTmpSlideId )
6552 .ReadUInt32( nTmpRef ); // this seems to be the instance
6553
6554 if ( ( nTmpSlideId == nSlideId ) && ( pHd->nRecInstance == nRefNum ) )
6555 {
6556 if (!pHd->SeekToEndOfRecord(rIn))
6557 break;
6558 ReadDffRecordHeader( rIn, aPresRuleHd );
6559 if ( aPresRuleHd.nRecType == PPT_PST_ExtendedParagraphAtom )
6560 {
6561 aExtParaHd = aPresRuleHd;
6562 break;
6563 }
6564 }
6565 pHd = pExtParaProv->
6566 aExtendedPresRules.GetRecordHeader( PPT_PST_ExtendedParagraphHeaderAtom,
6567 SEEK_FROM_CURRENT_AND_RESTART );
6568 if ( pHd == pFirst )
6569 break;
6570 }
6571 rIn.Seek( nOldPos );
6572 }
6573 // now pHd points to the right SlideListWithText Container
6574 PptSlidePersistList* pPageList = rSdrPowerPointImport.GetPageList( rSdrPowerPointImport.m_eCurrentPageKind );
6575 PptSlidePersistEntry* pE = nullptr;
6576 if ( pPageList && ( rSdrPowerPointImport.m_nCurrentPageNum < pPageList->size() ) )
6577 pE = &(*pPageList)[ rSdrPowerPointImport.m_nCurrentPageNum ];
6578 if ( (!pE) || (!pE->nSlidePersistStartOffset) || ( pE->aPersistAtom.nSlideId != nSlideId ) )
6579 bStatus = false;
6580 else
6581 {
6582 auto nOffset(pE->nSlidePersistStartOffset);
6583 bStatus = (nOffset == rIn.Seek(nOffset));
6584 // now we got the right page and are searching for the right
6585 // TextHeaderAtom
6586 auto nEndRecPos = DffPropSet::SanitizeEndPos(rIn, pE->nSlidePersistEndOffset);
6587 while (bStatus && rIn.Tell() < nEndRecPos)
6588 {
6589 ReadDffRecordHeader( rIn, aClientTextBoxHd );
6590 if ( aClientTextBoxHd.nRecType == PPT_PST_TextHeaderAtom )
6591 {
6592 if ( aClientTextBoxHd.nRecInstance == nRefNum )
6593 {
6594 aClientTextBoxHd.SeekToEndOfRecord( rIn );
6595 break;
6596 }
6597 }
6598 if (!aClientTextBoxHd.SeekToEndOfRecord(rIn))
6599 break;
6600 }
6601 if ( rIn.Tell() > pE->nSlidePersistEndOffset )
6602 bStatus = false;
6603 else
6604 { // patching the RecordHeader
6605 aClientTextBoxHd.nFilePos -= DFF_COMMON_RECORD_HEADER_SIZE;
6606 aClientTextBoxHd.nRecLen += DFF_COMMON_RECORD_HEADER_SIZE;
6607 aClientTextBoxHd.nRecType = DFF_msofbtClientTextbox;
6608 aClientTextBoxHd.nRecVer = DFF_PSFLAG_CONTAINER;
6609
6610 // we have to calculate the correct record len
6611 DffRecordHeader aTmpHd;
6612 nEndRecPos = DffPropSet::SanitizeEndPos(rIn, pE->nSlidePersistEndOffset);
6613 while (rIn.Tell() < nEndRecPos)
6614 {
6615 ReadDffRecordHeader( rIn, aTmpHd );
6616 if ( ( aTmpHd.nRecType == PPT_PST_SlidePersistAtom ) || ( aTmpHd.nRecType == PPT_PST_TextHeaderAtom ) )
6617 break;
6618 if (!aTmpHd.SeekToEndOfRecord(rIn))
6619 break;
6620 aClientTextBoxHd.nRecLen += aTmpHd.nRecLen + DFF_COMMON_RECORD_HEADER_SIZE;
6621 }
6622 aClientTextBoxHd.SeekToContent( rIn );
6623 }
6624 }
6625 }
6626 }
6627 }
6628
6629 if ( !bStatus )
6630 return;
6631
6632 if ( !SvxMSDffManager::SeekToRec( rIn, PPT_PST_TextHeaderAtom, aClientTextBoxHd.GetRecEndFilePos(), &aTextHd ) )
6633 return;
6634
6635 // TextHeaderAtom is always the first Atom
6636 sal_uInt16 nTmp;
6637 rIn.ReadUInt16( nTmp ); // this number tells us the TxMasterStyleAtom Instance
6638 if ( nTmp > 8 )
6639 nTmp = 4;
6640 TSS_Type nInstance = static_cast<TSS_Type>(nTmp);
6641 aTextHd.SeekToEndOfRecord( rIn );
6642 mxImplTextObj->mnInstance = nInstance;
6643
6644 sal_uInt32 nFilePos = rIn.Tell();
6645 if ( !(rSdrPowerPointImport.SeekToRec2( PPT_PST_TextBytesAtom,
6646 PPT_PST_TextCharsAtom,
6647 aClientTextBoxHd.GetRecEndFilePos() )
6648 || SvxMSDffManager::SeekToRec( rIn,
6649 PPT_PST_StyleTextPropAtom,
6650 aClientTextBoxHd.GetRecEndFilePos() )) )
6651 return;
6652
6653 PPTTextRulerInterpreter aTextRulerInterpreter( nTextRulerAtomOfs, aClientTextBoxHd, rIn );
6654
6655 PPTStyleTextPropReader aStyleTextPropReader( rIn, aClientTextBoxHd,
6656 aTextRulerInterpreter, aExtParaHd, nInstance );
6657 sal_uInt32 nParagraphs = mxImplTextObj->mnParagraphCount = aStyleTextPropReader.aParaPropList.size();
6658 if ( !nParagraphs )
6659 return;
6660
6661 // the language settings will be merged into the list of PPTCharPropSet
6662 DffRecordHeader aTextSpecInfoHd;
6663 PPTTextSpecInfoAtomInterpreter aTextSpecInfoAtomInterpreter;
6664 if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_TextSpecInfoAtom,
6665 aClientTextBoxHd.GetRecEndFilePos(), &aTextSpecInfoHd ) )
6666 {
6667 if ( aTextSpecInfoAtomInterpreter.Read( rIn, aTextSpecInfoHd, PPT_PST_TextSpecInfoAtom,
6668 &(rSdrPowerPointImport.m_pPPTStyleSheet->maTxSI) ) )
6669 {
6670 size_t nI = 0;
6671 for (const PPTTextSpecInfo& rSpecInfo : aTextSpecInfoAtomInterpreter.aList)
6672 {
6673 sal_uInt32 nCharIdx = rSpecInfo.nCharIdx;
6674
6675 // portions and text have to been split in some cases
6676 for ( ; nI < aStyleTextPropReader.aCharPropList.size(); ++nI)
6677 {
6678 PPTCharPropSet* pSet = aStyleTextPropReader.aCharPropList[nI].get();
6679 if (pSet->mnOriginalTextPos >= nCharIdx)
6680 break;
6681 pSet->mnLanguage[0] = rSpecInfo.nLanguage[0];
6682 pSet->mnLanguage[1] = rSpecInfo.nLanguage[1];
6683 pSet->mnLanguage[2] = rSpecInfo.nLanguage[2];
6684 // test if the current portion needs to be split
6685 if (pSet->maString.getLength() <= 1)
6686 continue;
6687 sal_Int32 nIndexOfNextPortion = pSet->maString.getLength() + pSet->mnOriginalTextPos;
6688 sal_Int32 nNewLen = nIndexOfNextPortion - nCharIdx;
6689 if (nNewLen <= 0)
6690 continue;
6691 sal_Int32 nOldLen = pSet->maString.getLength() - nNewLen;
6692 if (nOldLen <= 0)
6693 continue;
6694 OUString aString(pSet->maString);
6695 PPTCharPropSet* pNew = new PPTCharPropSet(*pSet);
6696 pSet->maString = aString.copy(0, nOldLen);
6697 pNew->maString = aString.copy(nOldLen, nNewLen);
6698 pNew->mnOriginalTextPos += nOldLen;
6699 aStyleTextPropReader.aCharPropList.emplace(aStyleTextPropReader.aCharPropList.begin() + nI + 1, pNew);
6700 }
6701 }
6702 }
6703 #ifdef DBG_UTIL
6704 else
6705 {
6706 if (!(rSdrPowerPointImport.rImportParam.nImportFlags & PPT_IMPORTFLAGS_NO_TEXT_ASSERT))
6707 {
6708 OSL_FAIL( "SdrTextSpecInfoAtomInterpreter::Ctor(): parsing error, this document needs to be analysed (SJ)" );
6709 }
6710 }
6711 #endif
6712 }
6713 // now will search for possible textextensions such as date/time fields
6714 // or ParaTabStops and append them on this textobj
6715 rIn.Seek( nFilePos );
6716 ::std::vector< std::unique_ptr<PPTFieldEntry> > FieldList;
6717 auto nEndRecPos = DffPropSet::SanitizeEndPos(rIn, aClientTextBoxHd.GetRecEndFilePos());
6718 while (rIn.Tell() < nEndRecPos)
6719 {
6720 ReadDffRecordHeader( rIn, aTextHd );
6721 sal_uInt16 nVal = 0;
6722 std::unique_ptr<PPTFieldEntry> xEntry;
6723 switch ( aTextHd.nRecType )
6724 {
6725 case PPT_PST_DateTimeMCAtom :
6726 {
6727 xEntry.reset(new PPTFieldEntry);
6728 rIn.ReadUInt16(xEntry->nPos)
6729 .ReadUInt16( nVal )
6730 .ReadUInt16( nVal );
6731 xEntry->SetDateTime( nVal & 0xff );
6732 }
6733 break;
6734
6735 case PPT_PST_FooterMCAtom :
6736 {
6737 xEntry.reset(new PPTFieldEntry);
6738 rIn.ReadUInt16(xEntry->nPos);
6739 xEntry->xField1.reset(new SvxFieldItem(SvxFooterField(), EE_FEATURE_FIELD));
6740 }
6741 break;
6742
6743 case PPT_PST_HeaderMCAtom :
6744 {
6745 xEntry.reset(new PPTFieldEntry);
6746 rIn.ReadUInt16(xEntry->nPos);
6747 xEntry->xField1.reset(new SvxFieldItem(SvxHeaderField(), EE_FEATURE_FIELD));
6748 }
6749 break;
6750
6751 case PPT_PST_GenericDateMCAtom :
6752 {
6753 xEntry.reset(new PPTFieldEntry);
6754 rIn.ReadUInt16(xEntry->nPos);
6755 xEntry->xField1.reset(new SvxFieldItem(SvxDateTimeField(), EE_FEATURE_FIELD));
6756 if (rPersistEntry.xHeaderFooterEntry) // sj: #i34111# on master pages it is possible
6757 { // that there is no HeaderFooterEntry available
6758 if (rPersistEntry.xHeaderFooterEntry->nAtom & 0x20000) // auto date time
6759 xEntry->SetDateTime(rPersistEntry.xHeaderFooterEntry->nAtom & 0xff);
6760 else
6761 xEntry->xString = rPersistEntry.xHeaderFooterEntry->pPlaceholder[nVal];
6762 }
6763 }
6764 break;
6765
6766 case PPT_PST_SlideNumberMCAtom :
6767 case PPT_PST_RTFDateTimeMCAtom :
6768 {
6769 xEntry.reset(new PPTFieldEntry);
6770 if ( aTextHd.nRecLen >= 4 )
6771 {
6772 rIn.ReadUInt16(xEntry->nPos)
6773 .ReadUInt16( nVal );
6774
6775 // evaluate ID
6776 //SvxFieldItem* pFieldItem = NULL;
6777 switch( aTextHd.nRecType )
6778 {
6779 case PPT_PST_SlideNumberMCAtom:
6780 xEntry->xField1.reset(new SvxFieldItem(SvxPageField(), EE_FEATURE_FIELD));
6781 break;
6782
6783 case PPT_PST_RTFDateTimeMCAtom:
6784 {
6785 // Rude workaround for one special case reported
6786 // by a customer. (#i75203#)
6787
6788 // Don't even attempt to handle the general use
6789 // case for PPT_PST_RTFDateTimeMCAtom (a generic
6790 // MS style date/time format string). Just handle
6791 // the special case where the format string
6792 // contains only one or several possibly empty
6793 // quoted strings. I.e. something that doesn't
6794 // expand to any date or time at all, but to a
6795 // fixed string. How on earth somebody manages to
6796 // produce such things in PPT slides I have no
6797 // idea.
6798 if (nVal == 0)
6799 {
6800 OUStringBuffer aStr;
6801 bool inquote = false;
6802 for (int nLen = 0; nLen < 64; ++nLen)
6803 {
6804 sal_Unicode n(0);
6805 rIn.ReadUtf16( n );
6806
6807 // Collect quoted characters into aStr
6808 if ( n == '\'')
6809 inquote = !inquote;
6810 else if (!n)
6811 {
6812 // End of format string
6813 xEntry->xString = aStr.makeStringAndClear();
6814 break;
6815 }
6816 else if (!inquote)
6817 {
6818 // Non-quoted character, i.e. a real
6819 // format specifier. We don't handle
6820 // those. Sorry.
6821 break;
6822 }
6823 else
6824 {
6825 aStr.append(OUStringChar(n));
6826 }
6827 }
6828 }
6829 if (!xEntry->xString)
6830 {
6831 // Handle as previously
6832 xEntry->xField1.reset(new SvxFieldItem( SvxDateField( Date( Date::SYSTEM ), SvxDateType::Fix ), EE_FEATURE_FIELD ));
6833 }
6834 }
6835 }
6836 }
6837 }
6838 break;
6839
6840 case PPT_PST_InteractiveInfo :
6841 {
6842 DffRecordHeader aHdInteractiveInfoAtom;
6843 if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_InteractiveInfoAtom, aTextHd.GetRecEndFilePos(), &aHdInteractiveInfoAtom ) )
6844 {
6845 PptInteractiveInfoAtom aInteractiveInfoAtom;
6846 ReadPptInteractiveInfoAtom( rIn, aInteractiveInfoAtom );
6847 for (const SdHyperlinkEntry& rHyperlink : rSdrPowerPointImport.m_aHyperList)
6848 {
6849 if ( rHyperlink.nIndex == aInteractiveInfoAtom.nExHyperlinkId )
6850 {
6851 if (!aTextHd.SeekToEndOfRecord(rIn))
6852 {
6853 break;
6854 }
6855 ReadDffRecordHeader( rIn, aTextHd );
6856 if ( aTextHd.nRecType != PPT_PST_TxInteractiveInfoAtom )
6857 {
6858 aTextHd.SeekToBegOfRecord( rIn );
6859 continue;
6860 }
6861 else
6862 {
6863 sal_uInt32 nStartPos, nEndPos;
6864 rIn.ReadUInt32( nStartPos )
6865 .ReadUInt32( nEndPos );
6866 if ( nEndPos )
6867 {
6868 xEntry.reset(new PPTFieldEntry);
6869 xEntry->nPos = static_cast<sal_uInt16>(nStartPos);
6870 xEntry->nTextRangeEnd = static_cast<sal_uInt16>(nEndPos);
6871 OUString aTarget( rHyperlink.aTarget );
6872 if ( !rHyperlink.aConvSubString.isEmpty() )
6873 {
6874 aTarget += "#" + rHyperlink.aConvSubString;
6875 }
6876 xEntry->xField1.reset(new SvxFieldItem( SvxURLField( aTarget, OUString(), SvxURLFormat::Repr ), EE_FEATURE_FIELD ));
6877 }
6878 }
6879 break;
6880 }
6881 }
6882 }
6883 }
6884 break;
6885 }
6886 if (!aTextHd.SeekToEndOfRecord(rIn))
6887 break;
6888 if (xEntry)
6889 {
6890 // sorting fields ( hi >> lo )
6891 auto it = std::find_if(FieldList.begin(), FieldList.end(),
6892 [&xEntry](const std::unique_ptr<PPTFieldEntry>& rxField) {
6893 return rxField->nPos < xEntry->nPos; });
6894 if ( it != FieldList.end() ) {
6895 FieldList.insert(it, std::move(xEntry));
6896 } else {
6897 FieldList.push_back( std::move(xEntry));
6898 }
6899 }
6900 }
6901 if ( !FieldList.empty() )
6902 {
6903 auto FE = FieldList.begin();
6904 auto& aCharPropList = aStyleTextPropReader.aCharPropList;
6905
6906 sal_Int32 i = nParagraphs - 1;
6907 sal_Int32 n = aCharPropList.size() - 1;
6908
6909 // at this point we just have a list of textportions(aCharPropList)
6910 // the next while loop tries to resolve the list of fields(pFieldList)
6911 while( ( FE < FieldList.end() ) && ( n >= 0 ) && ( i >= 0 ) )
6912 {
6913 PPTCharPropSet* pSet = aCharPropList[n].get();
6914 OUString aString( pSet->maString );
6915 sal_uInt32 nCount = aString.getLength();
6916 sal_uInt32 nPos = pSet->mnOriginalTextPos + nCount;
6917 while ( ( FE < FieldList.end() ) && nCount-- )
6918 {
6919 nPos--;
6920 FE = std::find_if(FE, FieldList.end(),
6921 [&nPos](const std::unique_ptr<PPTFieldEntry>& rxField) {return rxField->nPos <= nPos;});
6922 if (FE == FieldList.end())
6923 break;
6924
6925 if ( (*FE)->nPos == nPos )
6926 {
6927 if ( aString[nCount] == 0x2a )
6928 {
6929 sal_uInt32 nBehind = aString.getLength() - ( nCount + 1 );
6930 pSet->maString.clear();
6931 if ( nBehind )
6932 {
6933 PPTCharPropSet* pNewCPS = new PPTCharPropSet( *pSet );
6934 pNewCPS->maString = aString.copy( nCount + 1, nBehind );
6935 aCharPropList.emplace( aCharPropList.begin() + n + 1, pNewCPS );
6936 }
6937 if ( (*FE)->xField2 )
6938 {
6939 PPTCharPropSet* pNewCPS = new PPTCharPropSet( *pSet );
6940 pNewCPS->mpFieldItem = std::move((*FE)->xField2);
6941 aCharPropList.emplace( aCharPropList.begin() + n + 1, pNewCPS );
6942
6943 pNewCPS = new PPTCharPropSet( *pSet );
6944 pNewCPS->maString = " ";
6945 aCharPropList.emplace( aCharPropList.begin() + n + 1, pNewCPS );
6946 }
6947 if ( nCount )
6948 {
6949 PPTCharPropSet* pNewCPS = new PPTCharPropSet( *pSet );
6950 pNewCPS->maString = aString.copy( 0, nCount );
6951 aCharPropList.emplace( aCharPropList.begin() + n++, pNewCPS );
6952 }
6953 if ( (*FE)->xField1 )
6954 {
6955 pSet->mpFieldItem = std::move((*FE)->xField1);
6956 }
6957 else if ( (*FE)->xString )
6958 pSet->maString = *(*FE)->xString;
6959 }
6960 else
6961 {
6962 if ( (*FE)->nTextRangeEnd ) // text range hyperlink
6963 {
6964 sal_uInt32 nHyperLen = (*FE)->nTextRangeEnd - nPos;
6965 if ( nHyperLen )
6966 {
6967 PPTCharPropSet* pBefCPS = nullptr;
6968 if ( nCount )
6969 {
6970 pBefCPS = new PPTCharPropSet( *pSet );
6971 pSet->maString = pSet->maString.copy(nCount);
6972 }
6973 sal_uInt32 nIdx = n;
6974 sal_Int32 nHyperLenLeft = nHyperLen;
6975
6976 while ( ( aCharPropList.size() > nIdx ) && nHyperLenLeft )
6977 {
6978 // the textrange hyperlink can take more than 1 paragraph
6979 // the solution here is to clone the hyperlink...
6980
6981 PPTCharPropSet* pCurrent = aCharPropList[ nIdx ].get();
6982 sal_Int32 nNextStringLen = pCurrent->maString.getLength();
6983
6984 DBG_ASSERT( (*FE)->xField1, "missing field!" );
6985 if (!(*FE)->xField1)
6986 break;
6987
6988 const SvxURLField* pField = static_cast<const SvxURLField*>((*FE)->xField1->GetField());
6989
6990 pCurrent->mbIsHyperlink = true;
6991 pCurrent->mnHylinkOrigColor = pCurrent->mpImplPPTCharPropSet->mnColor;
6992 pCurrent->mbHardHylinkOrigColor = ( ( pCurrent->mpImplPPTCharPropSet->mnAttrSet >>PPT_CharAttr_FontColor ) & 1)>0;
6993
6994 // add missing attribute to show underline property
6995 pCurrent->mpImplPPTCharPropSet->mnAttrSet |= 1 << PPT_CharAttr_Underline;
6996 pCurrent->mpImplPPTCharPropSet->mnFlags = 1 << PPT_CharAttr_Underline;
6997
6998 if ( pCurrent->mpFieldItem )
6999 {
7000 pCurrent->SetColor( PPT_COLSCHEME_A_UND_HYPERLINK );
7001 if ( dynamic_cast< const SvxURLField* >(pCurrent->mpFieldItem->GetField()) != nullptr)
7002 break;
7003 nHyperLenLeft--;
7004 }
7005 else if ( nNextStringLen )
7006 {
7007 if ( nNextStringLen <= nHyperLenLeft )
7008 {
7009 pCurrent->mpFieldItem.reset( new SvxFieldItem( SvxURLField( pField->GetURL(), pCurrent->maString, SvxURLFormat::Repr ), EE_FEATURE_FIELD ) );
7010 nHyperLenLeft -= nNextStringLen;
7011
7012 if ( nHyperLenLeft )
7013 {
7014 // if the next portion is in a higher paragraph,
7015 // the textrange is to decrease (because of the LineBreak character)
7016 if ( aCharPropList.size() > ( nIdx + 1 ) )
7017 {
7018 PPTCharPropSet* pNext = aCharPropList[ nIdx + 1 ].get();
7019 if ( pNext->mnParagraph > pCurrent->mnParagraph )
7020 nHyperLenLeft--;
7021 }
7022 }
7023 }
7024 else
7025 {
7026 PPTCharPropSet* pNewCPS = new PPTCharPropSet( *pCurrent );
7027 pNewCPS->maString = pCurrent->maString.copy( nHyperLenLeft,( nNextStringLen - nHyperLenLeft ) );
7028 aCharPropList.emplace( aCharPropList.begin() + nIdx + 1, pNewCPS );
7029 OUString aRepresentation = pCurrent->maString.copy( 0, nHyperLenLeft );
7030 pCurrent->mpFieldItem.reset( new SvxFieldItem( SvxURLField( pField->GetURL(), aRepresentation, SvxURLFormat::Repr ), EE_FEATURE_FIELD ) );
7031 nHyperLenLeft = 0;
7032 }
7033 pCurrent->maString.clear();
7034 pCurrent->SetColor( PPT_COLSCHEME_A_UND_HYPERLINK );
7035 }
7036 nIdx++;
7037 }
7038 (*FE)->xField1.reset();
7039
7040 if ( pBefCPS )
7041 {
7042 pBefCPS->maString = aString.copy( 0, nCount );
7043 aCharPropList.emplace( aCharPropList.begin() + n, pBefCPS );
7044 n++;
7045 }
7046 }
7047 }
7048 }
7049 break;
7050 }
7051 }
7052 n--;
7053 }
7054 }
7055 mxImplTextObj->maParagraphList.resize( nParagraphs );
7056 for (size_t nCurCharPos = 0, nCurPos = 0;
7057 nCurPos < aStyleTextPropReader.aParaPropList.size();
7058 ++nCurPos)
7059 {
7060 mxImplTextObj->maParagraphList[ nCurPos ].reset(
7061 new PPTParagraphObj(
7062 aStyleTextPropReader, nCurPos, nCurCharPos,
7063 *rSdrPowerPointImport.m_pPPTStyleSheet,
7064 nInstance, aTextRulerInterpreter ) );
7065
7066 sal_uInt32 nParaAdjust, nFlags = 0;
7067 mxImplTextObj->maParagraphList[ nCurPos ]->GetAttrib( PPT_ParaAttr_Adjust, nParaAdjust, GetInstance() );
7068
7069 switch ( nParaAdjust )
7070 {
7071 case 0 : nFlags = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT; break;
7072 case 1 : nFlags = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER; break;
7073 case 2 : nFlags = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT; break;
7074 case 3 : nFlags = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK; break;
7075 }
7076 mxImplTextObj->mnTextFlags |= nFlags;
7077 }
7078 }
7079
PPTTextObj(PPTTextObj const & rTextObj)7080 PPTTextObj::PPTTextObj( PPTTextObj const & rTextObj )
7081 {
7082 mxImplTextObj = rTextObj.mxImplTextObj;
7083 }
7084
~PPTTextObj()7085 PPTTextObj::~PPTTextObj()
7086 {
7087 }
7088
First()7089 PPTParagraphObj* PPTTextObj::First()
7090 {
7091 mxImplTextObj->mnCurrentObject = 0;
7092 if ( !mxImplTextObj->mnParagraphCount )
7093 return nullptr;
7094 return mxImplTextObj->maParagraphList[ 0 ].get();
7095 }
7096
Next()7097 PPTParagraphObj* PPTTextObj::Next()
7098 {
7099 sal_uInt32 i = mxImplTextObj->mnCurrentObject + 1;
7100 if ( i >= mxImplTextObj->mnParagraphCount )
7101 return nullptr;
7102 mxImplTextObj->mnCurrentObject++;
7103 return mxImplTextObj->maParagraphList[ i ].get();
7104 }
7105
GetBackground() const7106 const SfxItemSet* PPTTextObj::GetBackground() const
7107 {
7108 if ( mxImplTextObj->mrPersistEntry.pBObj )
7109 return &mxImplTextObj->mrPersistEntry.pBObj->GetMergedItemSet();
7110 else
7111 return nullptr;
7112 }
7113
operator =(PPTTextObj & rTextObj)7114 PPTTextObj& PPTTextObj::operator=( PPTTextObj& rTextObj )
7115 {
7116 if ( this != &rTextObj )
7117 {
7118 mxImplTextObj = rTextObj.mxImplTextObj;
7119 }
7120 return *this;
7121 }
7122
IsLine(const SdrObject * pObj)7123 static bool IsLine( const SdrObject* pObj )
7124 {
7125 auto pSdrPathObj = dynamic_cast< const SdrPathObj* >(pObj);
7126 return pSdrPathObj && pSdrPathObj->IsLine() && pSdrPathObj->GetPointCount() == 2;
7127 }
7128
GetCellPosition(const SdrObject * pObj,const o3tl::sorted_vector<sal_Int32> & rRows,const o3tl::sorted_vector<sal_Int32> & rColumns,sal_Int32 & nTableIndex,sal_Int32 & nRow,sal_Int32 & nRowCount,sal_Int32 & nColumn,sal_Int32 & nColumnCount)7129 static bool GetCellPosition( const SdrObject* pObj, const o3tl::sorted_vector< sal_Int32 >& rRows, const o3tl::sorted_vector< sal_Int32 >& rColumns,
7130 sal_Int32& nTableIndex, sal_Int32& nRow, sal_Int32& nRowCount, sal_Int32& nColumn, sal_Int32& nColumnCount )
7131 {
7132 tools::Rectangle aSnapRect( pObj->GetSnapRect() );
7133 bool bCellObject = ( aSnapRect.GetWidth() > 1 ) && ( aSnapRect.GetHeight() > 1 );
7134 if ( bCellObject )
7135 {
7136 auto aRowIter = rRows.find( aSnapRect.Top() );
7137 auto aColumnIter = rColumns.find( aSnapRect.Left() );
7138 if ( ( aRowIter == rRows.end() ) || ( aColumnIter == rColumns.end() ) )
7139 bCellObject = false;
7140 else
7141 {
7142 nRowCount = 1;
7143 nRow = std::distance( rRows.begin(), aRowIter );
7144 while( ++aRowIter != rRows.end() )
7145 {
7146 if ( *aRowIter >= aSnapRect.Bottom() )
7147 break;
7148 nRowCount++;
7149 }
7150 nColumnCount = 1;
7151 nColumn = std::distance( rColumns.begin(), aColumnIter );
7152 while( ++aColumnIter != rColumns.end() )
7153 {
7154 if ( *aColumnIter >= aSnapRect.Right() )
7155 break;
7156 nColumnCount++;
7157 }
7158 nTableIndex = nRow * rColumns.size() + nColumn;
7159 }
7160 }
7161 return bCellObject;
7162 }
7163
7164 #define LinePositionLeft 0x01000000
7165 #define LinePositionTop 0x02000000
7166 #define LinePositionRight 0x04000000
7167 #define LinePositionBottom 0x08000000
7168 #define LinePositionTLBR 0x10000000
7169 #define LinePositionBLTR 0x20000000
7170
7171
GetRowPositions(const tools::Rectangle & rSnapRect,const o3tl::sorted_vector<sal_Int32> & rRows,const o3tl::sorted_vector<sal_Int32> & rColumns,std::vector<sal_Int32> & rPositions,sal_Int32 nColumn,sal_Int32 nFlags)7172 static void GetRowPositions( const tools::Rectangle& rSnapRect, const o3tl::sorted_vector< sal_Int32 >& rRows,
7173 const o3tl::sorted_vector< sal_Int32 >& rColumns, std::vector< sal_Int32 >& rPositions, sal_Int32 nColumn, sal_Int32 nFlags )
7174 {
7175 auto aRow = rRows.find( rSnapRect.Top() );
7176 if ( aRow == rRows.end() )
7177 return;
7178
7179 sal_Int32 nRow = std::distance( rRows.begin(), aRow );
7180 while( ( aRow != rRows.end() ) && ((*aRow) < rSnapRect.Bottom() ) )
7181 {
7182 if ( nFlags & LinePositionLeft )
7183 rPositions.push_back( ( ( nRow * rColumns.size() ) + nColumn ) | LinePositionLeft );
7184 if ( nFlags & LinePositionRight )
7185 rPositions.push_back( ( ( nRow * rColumns.size() ) + ( nColumn - 1 ) ) | LinePositionRight );
7186
7187 ++nRow;
7188 ++aRow;
7189 }
7190 }
7191
7192
GetColumnPositions(const tools::Rectangle & rSnapRect,const o3tl::sorted_vector<sal_Int32> & rColumns,std::vector<sal_Int32> & rPositions,sal_Int32 nRow,sal_Int32 nFlags)7193 static void GetColumnPositions( const tools::Rectangle& rSnapRect,
7194 const o3tl::sorted_vector< sal_Int32 >& rColumns, std::vector< sal_Int32 >& rPositions, sal_Int32 nRow, sal_Int32 nFlags )
7195 {
7196 auto aColumn = rColumns.find( rSnapRect.Left() );
7197 if ( aColumn == rColumns.end() )
7198 return;
7199
7200 sal_Int32 nColumn = std::distance( rColumns.begin(), aColumn );
7201 while( ( aColumn != rColumns.end() ) && ((*aColumn) < rSnapRect.Right() ) )
7202 {
7203 if ( nFlags & LinePositionTop )
7204 rPositions.push_back( ( ( nRow * rColumns.size() ) + nColumn ) | LinePositionTop );
7205 if ( nFlags & LinePositionBottom )
7206 rPositions.push_back( ( ( ( nRow - 1 ) * rColumns.size() ) + nColumn ) | LinePositionBottom );
7207
7208 ++nColumn;
7209 ++aColumn;
7210 }
7211 }
7212
GetLinePositions(const SdrObject * pObj,const o3tl::sorted_vector<sal_Int32> & rRows,const o3tl::sorted_vector<sal_Int32> & rColumns,std::vector<sal_Int32> & rPositions,const tools::Rectangle & rGroupSnap)7213 static void GetLinePositions( const SdrObject* pObj, const o3tl::sorted_vector< sal_Int32 >& rRows, const o3tl::sorted_vector< sal_Int32 >& rColumns,
7214 std::vector< sal_Int32 >& rPositions, const tools::Rectangle& rGroupSnap )
7215 {
7216 tools::Rectangle aSnapRect( pObj->GetSnapRect() );
7217 if ( aSnapRect.Left() == aSnapRect.Right() )
7218 {
7219 auto aColumn = rColumns.find( aSnapRect.Left() );
7220 if ( ( aColumn != rColumns.end() ) || ( aSnapRect.Left() == rGroupSnap.Right() ) )
7221 {
7222 sal_Int32 nColumn, nFlags;
7223 if ( aColumn != rColumns.end() )
7224 {
7225 nColumn = std::distance( rColumns.begin(), aColumn );
7226 nFlags = LinePositionLeft;
7227 if ( aColumn != rColumns.begin() )
7228 nFlags |= LinePositionRight;
7229 }
7230 else
7231 {
7232 nColumn = rColumns.size();
7233 nFlags = LinePositionRight;
7234 }
7235 GetRowPositions( aSnapRect, rRows, rColumns, rPositions, nColumn, nFlags );
7236 }
7237 }
7238 else if ( aSnapRect.Top() == aSnapRect.Bottom() )
7239 {
7240 auto aRow = rRows.find( aSnapRect.Top() );
7241 if ( ( aRow != rRows.end() ) || ( aSnapRect.Top() == rGroupSnap.Bottom() ) )
7242 {
7243 sal_Int32 nRow, nFlags;
7244 if ( aRow != rRows.end() )
7245 {
7246 nRow = std::distance( rRows.begin(), aRow );
7247 nFlags = LinePositionTop;
7248 if ( aRow != rRows.begin() )
7249 nFlags |= LinePositionBottom;
7250 }
7251 else
7252 {
7253 nRow = rRows.size();
7254 nFlags = LinePositionBottom;
7255 }
7256 GetColumnPositions( aSnapRect, rColumns, rPositions, nRow, nFlags );
7257 }
7258 }
7259 else
7260 {
7261 sal_uInt32 nPosition = 0;
7262 Point aPt1( static_cast<const SdrPathObj*>(pObj)->GetPoint( 0 ) );
7263 Point aPt2( static_cast<const SdrPathObj*>(pObj)->GetPoint( 1 ) );
7264 if ( aPt1.X() < aPt2.X() )
7265 nPosition |= aPt1.Y() < aPt2.Y() ? LinePositionTLBR : LinePositionBLTR;
7266 else
7267 nPosition |= aPt1.Y() < aPt2.Y() ? LinePositionBLTR : LinePositionTLBR;
7268
7269 auto aRow = rRows.find( std::min(aPt1.Y(), aPt2.Y() ) );
7270 auto aColumn = rColumns.find( std::min(aPt1.X(), aPt2.X() ) );
7271 if ( ( aRow != rRows.end() ) && ( aColumn != rColumns.end() ) )
7272 {
7273 nPosition |= ( std::distance( rRows.begin(), aRow ) * rColumns.size() ) + std::distance( rColumns.begin(), aColumn );
7274 rPositions.push_back( nPosition );
7275 }
7276 }
7277 }
7278
CreateTableRows(const Reference<XTableRows> & xTableRows,const o3tl::sorted_vector<sal_Int32> & rRows,sal_Int32 nTableBottom)7279 static void CreateTableRows( const Reference< XTableRows >& xTableRows, const o3tl::sorted_vector< sal_Int32 >& rRows, sal_Int32 nTableBottom )
7280 {
7281 if ( rRows.size() > 1 )
7282 xTableRows->insertByIndex( 0, rRows.size() - 1 );
7283
7284 auto aIter = rRows.begin();
7285 sal_Int32 nLastPosition( *aIter );
7286 for ( sal_Int32 n = 0; n < xTableRows->getCount(); n++ )
7287 {
7288 sal_Int32 nHeight;
7289 if ( ++aIter != rRows.end() )
7290 {
7291 if (o3tl::checked_sub<sal_Int32>(*aIter, nLastPosition, nHeight))
7292 throw lang::IllegalArgumentException();
7293 nLastPosition = *aIter;
7294 }
7295 else
7296 {
7297 if (o3tl::checked_sub<sal_Int32>(nTableBottom, nLastPosition, nHeight))
7298 throw lang::IllegalArgumentException();
7299 }
7300
7301 Reference< XPropertySet > xPropSet( xTableRows->getByIndex( n ), UNO_QUERY_THROW );
7302 xPropSet->setPropertyValue( "Height", Any( nHeight ) );
7303 }
7304 }
7305
CreateTableColumns(const Reference<XTableColumns> & xTableColumns,const o3tl::sorted_vector<sal_Int32> & rColumns,sal_Int32 nTableRight)7306 static void CreateTableColumns( const Reference< XTableColumns >& xTableColumns, const o3tl::sorted_vector< sal_Int32 >& rColumns, sal_Int32 nTableRight )
7307 {
7308 if ( rColumns.size() > 1 )
7309 xTableColumns->insertByIndex( 0, rColumns.size() - 1 );
7310
7311 auto aIter = rColumns.begin();
7312 sal_Int32 nLastPosition( *aIter );
7313 for ( sal_Int32 n = 0; n < xTableColumns->getCount(); n++ )
7314 {
7315 sal_Int32 nWidth;
7316 if ( ++aIter != rColumns.end() )
7317 {
7318 if (o3tl::checked_sub<sal_Int32>(*aIter, nLastPosition, nWidth))
7319 throw lang::IllegalArgumentException();
7320 nLastPosition = *aIter;
7321 }
7322 else
7323 {
7324 if (o3tl::checked_sub<sal_Int32>(nTableRight, nLastPosition, nWidth))
7325 throw lang::IllegalArgumentException();
7326 }
7327
7328 Reference< XPropertySet > xPropSet( xTableColumns->getByIndex( n ), UNO_QUERY_THROW );
7329 xPropSet->setPropertyValue( "Width", Any( nWidth ) );
7330 }
7331 }
7332
MergeCells(const Reference<XTable> & xTable,sal_Int32 nCol,sal_Int32 nRow,sal_Int32 nColSpan,sal_Int32 nRowSpan)7333 static void MergeCells( const Reference< XTable >& xTable, sal_Int32 nCol, sal_Int32 nRow, sal_Int32 nColSpan, sal_Int32 nRowSpan )
7334 {
7335 DBG_ASSERT( (nColSpan > 1) || (nRowSpan > 1), "nonsense parameter!!" );
7336 DBG_ASSERT( (nCol >= 0) && (nCol < xTable->getColumnCount()) && (nRow >= 0) && (nRow < xTable->getRowCount()), "the cell does not exists!!" );
7337 DBG_ASSERT( (nColSpan >= 1) && ((nCol + nColSpan - 1) < xTable->getColumnCount()), "nColSpan botch!" );
7338 DBG_ASSERT( (nRowSpan >= 1) && ((nRow + nRowSpan - 1) < xTable->getRowCount()), "nRowSpan botch!" );
7339
7340 if( xTable.is() ) try
7341 {
7342 Reference< XMergeableCellRange > xRange( xTable->createCursorByRange( xTable->getCellRangeByPosition( nCol, nRow,nCol + nColSpan - 1, nRow + nRowSpan - 1 ) ), UNO_QUERY_THROW );
7343 if( xRange->isMergeable() )
7344 xRange->merge();
7345 }
7346 catch( const Exception& )
7347 {
7348 DBG_UNHANDLED_EXCEPTION("filter.ms");
7349 }
7350 }
7351
ApplyCellAttributes(const SdrObject * pObj,Reference<XCell> const & xCell)7352 static void ApplyCellAttributes( const SdrObject* pObj, Reference< XCell > const & xCell )
7353 {
7354 try
7355 {
7356 Reference< XPropertySet > xPropSet( xCell, UNO_QUERY_THROW );
7357
7358 const sal_Int32 nLeftDist(pObj->GetMergedItem(SDRATTR_TEXT_LEFTDIST).GetValue());
7359 const sal_Int32 nRightDist(pObj->GetMergedItem(SDRATTR_TEXT_RIGHTDIST).GetValue());
7360 const sal_Int32 nUpperDist(pObj->GetMergedItem(SDRATTR_TEXT_UPPERDIST).GetValue());
7361 const sal_Int32 nLowerDist(pObj->GetMergedItem(SDRATTR_TEXT_LOWERDIST).GetValue());
7362 xPropSet->setPropertyValue( "TextUpperDistance", Any( nUpperDist ) );
7363 xPropSet->setPropertyValue( "TextRightDistance", Any( nRightDist ) );
7364 xPropSet->setPropertyValue( "TextLeftDistance", Any( nLeftDist ) );
7365 xPropSet->setPropertyValue( "TextLowerDistance", Any( nLowerDist ) );
7366
7367 const SdrTextVertAdjust eTextVertAdjust(pObj->GetMergedItem(SDRATTR_TEXT_VERTADJUST).GetValue());
7368 drawing::TextVerticalAdjust eVA( drawing::TextVerticalAdjust_TOP );
7369 if ( eTextVertAdjust == SDRTEXTVERTADJUST_CENTER )
7370 eVA = drawing::TextVerticalAdjust_CENTER;
7371 else if ( eTextVertAdjust == SDRTEXTVERTADJUST_BOTTOM )
7372 eVA = drawing::TextVerticalAdjust_BOTTOM;
7373 xPropSet->setPropertyValue( "TextVerticalAdjust", Any( eVA ) );
7374
7375 //set textHorizontalAdjust and TextWritingMode attr
7376 const sal_Int32 eHA(pObj->GetMergedItem(SDRATTR_TEXT_HORZADJUST).GetValue());
7377 const SvxFrameDirection eDirection = pObj->GetMergedItem(EE_PARA_WRITINGDIR).GetValue();
7378 xPropSet->setPropertyValue( "TextHorizontalAdjust" , Any( eHA ) );
7379 if ( eDirection == SvxFrameDirection::Vertical_RL_TB )
7380 {//vertical writing
7381 xPropSet->setPropertyValue( "TextWritingMode" , Any( css::text::WritingMode_TB_RL ) );
7382 }
7383 drawing::FillStyle eFillStyle(pObj->GetMergedItem( XATTR_FILLSTYLE ).GetValue());
7384 css::drawing::FillStyle eFS( css::drawing::FillStyle_NONE );
7385 switch( eFillStyle )
7386 {
7387 case drawing::FillStyle_SOLID :
7388 {
7389 eFS = css::drawing::FillStyle_SOLID;
7390 Color aFillColor( pObj->GetMergedItem( XATTR_FILLCOLOR ).GetColorValue() );
7391 xPropSet->setPropertyValue( "FillColor", makeAny( aFillColor ) );
7392 }
7393 break;
7394 case drawing::FillStyle_GRADIENT :
7395 {
7396 eFS = css::drawing::FillStyle_GRADIENT;
7397 XGradient aXGradient(pObj->GetMergedItem(XATTR_FILLGRADIENT).GetGradientValue());
7398
7399 css::awt::Gradient aGradient;
7400 aGradient.Style = aXGradient.GetGradientStyle();
7401 aGradient.StartColor = static_cast<sal_Int32>(aXGradient.GetStartColor());
7402 aGradient.EndColor = static_cast<sal_Int32>(aXGradient.GetEndColor());
7403 aGradient.Angle = static_cast<short>(aXGradient.GetAngle());
7404 aGradient.Border = aXGradient.GetBorder();
7405 aGradient.XOffset = aXGradient.GetXOffset();
7406 aGradient.YOffset = aXGradient.GetYOffset();
7407 aGradient.StartIntensity = aXGradient.GetStartIntens();
7408 aGradient.EndIntensity = aXGradient.GetEndIntens();
7409 aGradient.StepCount = aXGradient.GetSteps();
7410
7411 xPropSet->setPropertyValue( "FillGradient", Any( aGradient ) );
7412 }
7413 break;
7414 case drawing::FillStyle_HATCH :
7415 eFS = css::drawing::FillStyle_HATCH;
7416 break;
7417 case drawing::FillStyle_BITMAP :
7418 {
7419 eFS = css::drawing::FillStyle_BITMAP;
7420
7421 const XFillBitmapItem & rXFillBitmapItem(pObj->GetMergedItem( XATTR_FILLBITMAP ));
7422 uno::Reference<graphic::XGraphic> xGraphic = rXFillBitmapItem.GetGraphicObject().GetGraphic().GetXGraphic();
7423 uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
7424 xPropSet->setPropertyValue("FillBitmap", uno::makeAny(xBitmap));
7425
7426 const XFillBmpStretchItem & rStretchItem(pObj->GetMergedItem( XATTR_FILLBMP_STRETCH ));
7427 const XFillBmpTileItem & rTileItem(pObj->GetMergedItem( XATTR_FILLBMP_TILE ));
7428 if( rTileItem.GetValue() )
7429 xPropSet->setPropertyValue("FillBitmapMode", uno::makeAny(drawing::BitmapMode_REPEAT));
7430 else if( rStretchItem.GetValue() )
7431 xPropSet->setPropertyValue("FillBitmapMode", uno::makeAny(drawing::BitmapMode_STRETCH));
7432 else
7433 xPropSet->setPropertyValue("FillBitmapMode", uno::makeAny(drawing::BitmapMode_NO_REPEAT));
7434 }
7435 break;
7436 default:
7437 case drawing::FillStyle_NONE :
7438 eFS = css::drawing::FillStyle_NONE;
7439 break;
7440
7441 }
7442 xPropSet->setPropertyValue( "FillStyle", Any( eFS ) );
7443 if ( eFillStyle != drawing::FillStyle_NONE )
7444 {
7445 sal_Int16 nFillTransparence( pObj->GetMergedItem( XATTR_FILLTRANSPARENCE ).GetValue() );
7446 xPropSet->setPropertyValue( "FillTransparence", Any( nFillTransparence ) );
7447 }
7448 }
7449 catch( const Exception& )
7450 {
7451 }
7452 }
7453
ApplyCellLineAttributes(const SdrObject * pLine,Reference<XTable> const & xTable,const std::vector<sal_Int32> & vPositions,sal_Int32 nColumns)7454 static void ApplyCellLineAttributes( const SdrObject* pLine, Reference< XTable > const & xTable, const std::vector< sal_Int32 >& vPositions, sal_Int32 nColumns )
7455 {
7456 try
7457 {
7458 drawing::LineStyle eLineStyle(pLine->GetMergedItem( XATTR_LINESTYLE ).GetValue());
7459 css::table::BorderLine2 aBorderLine;
7460 switch( eLineStyle )
7461 {
7462 case drawing::LineStyle_DASH :
7463 case drawing::LineStyle_SOLID :
7464 {
7465 Color aLineColor( pLine->GetMergedItem( XATTR_LINECOLOR ).GetColorValue() );
7466 aBorderLine.Color = sal_Int32(aLineColor);
7467 // Avoid width = 0, the min value should be 1.
7468 sal_Int32 nLineWidth = std::max(sal_Int32(1), pLine->GetMergedItem(XATTR_LINEWIDTH) .GetValue() / 4);
7469 aBorderLine.LineWidth = static_cast< sal_Int16 >( nLineWidth );
7470 aBorderLine.LineStyle = eLineStyle == drawing::LineStyle_SOLID ? table::BorderLineStyle::SOLID : table::BorderLineStyle::DASHED;
7471 }
7472 break;
7473 default:
7474 case drawing::LineStyle_NONE :
7475 {
7476 aBorderLine.LineWidth = 0;
7477 aBorderLine.LineStyle = table::BorderLineStyle::NONE;
7478 }
7479 break;
7480 }
7481 for (auto const& vPos : vPositions)
7482 {
7483 sal_Int32 nPosition = vPos & 0xffffff;
7484 sal_Int32 nFlags = vPos &~0xffffff;
7485 sal_Int32 nRow = nPosition / nColumns;
7486 sal_Int32 nColumn = nPosition - ( nRow * nColumns );
7487 Reference< XCell > xCell( xTable->getCellByPosition( nColumn, nRow ) );
7488 Reference< XPropertySet > xPropSet( xCell, UNO_QUERY_THROW );
7489
7490 if ( nFlags & LinePositionLeft )
7491 xPropSet->setPropertyValue( "LeftBorder", Any( aBorderLine ) );
7492 if ( nFlags & LinePositionTop )
7493 xPropSet->setPropertyValue( "TopBorder", Any( aBorderLine ) );
7494 if ( nFlags & LinePositionRight )
7495 xPropSet->setPropertyValue( "RightBorder", Any( aBorderLine ) );
7496 if ( nFlags & LinePositionBottom )
7497 xPropSet->setPropertyValue( "BottomBorder", Any( aBorderLine ) );
7498 if ( nFlags & LinePositionTLBR )
7499 xPropSet->setPropertyValue( "DiagonalTLBR", Any( true ) );
7500 if ( nFlags & LinePositionBLTR )
7501 xPropSet->setPropertyValue( "DiagonalBLTR", Any( true ) );
7502 }
7503 }
7504 catch( const Exception& )
7505 {
7506 }
7507 }
7508
CreateTable(SdrObject * pGroup,const sal_uInt32 * pTableArry,SvxMSDffSolverContainer * pSolverContainer,std::vector<SdrObject * > & rBackgroundColoredObjects)7509 SdrObject* SdrPowerPointImport::CreateTable(SdrObject* pGroup, const sal_uInt32* pTableArry, SvxMSDffSolverContainer* pSolverContainer, std::vector<SdrObject*>& rBackgroundColoredObjects)
7510 {
7511 SdrObject* pRet = pGroup;
7512
7513 sal_uInt32 nRows = pTableArry[ 1 ];
7514 if (!nRows)
7515 return pRet;
7516
7517 const SdrObjGroup* pObjGroup = dynamic_cast<const SdrObjGroup*>(pGroup);
7518 if (!pObjGroup)
7519 return pRet;
7520
7521 SdrObjList* pSubList(pObjGroup->GetSubList());
7522 if (!pSubList)
7523 return pRet;
7524
7525 o3tl::sorted_vector< sal_Int32 > aRows;
7526 o3tl::sorted_vector< sal_Int32 > aColumns;
7527
7528 SdrObjListIter aGroupIter( pSubList, SdrIterMode::DeepNoGroups, false );
7529 while( aGroupIter.IsMore() )
7530 {
7531 const SdrObject* pObj( aGroupIter.Next() );
7532 if ( !IsLine( pObj ) )
7533 {
7534 tools::Rectangle aSnapRect( pObj->GetSnapRect() );
7535 aRows.insert( aSnapRect.Top() );
7536 aColumns.insert( aSnapRect.Left() );
7537 }
7538 }
7539
7540 if (aRows.empty())
7541 return pRet;
7542
7543 sdr::table::SdrTableObj* pTable = new sdr::table::SdrTableObj(*pSdrModel);
7544 pTable->uno_lock();
7545 Reference< XTable > xTable( pTable->getTable() );
7546
7547 try
7548 {
7549 CreateTableRows( xTable->getRows(), aRows, pGroup->GetSnapRect().Bottom() );
7550 CreateTableColumns( xTable->getColumns(), aColumns, pGroup->GetSnapRect().Right() );
7551
7552 sal_Int32 nCellCount = aRows.size() * aColumns.size();
7553 std::unique_ptr<sal_Int32[]> pMergedCellIndexTable(new sal_Int32[ nCellCount ]);
7554 for ( sal_Int32 i = 0; i < nCellCount; i++ )
7555 pMergedCellIndexTable[ i ] = i;
7556
7557 aGroupIter.Reset();
7558 while( aGroupIter.IsMore() )
7559 {
7560 SdrObject* pObj( aGroupIter.Next() );
7561 if ( !IsLine( pObj ) )
7562 {
7563 sal_Int32 nTableIndex = 0;
7564 sal_Int32 nRow = 0;
7565 sal_Int32 nRowCount = 0;
7566 sal_Int32 nColumn = 0;
7567 sal_Int32 nColumnCount = 0;
7568 if ( GetCellPosition( pObj, aRows, aColumns, nTableIndex, nRow, nRowCount, nColumn, nColumnCount ) )
7569 {
7570 Reference< XCell > xCell( xTable->getCellByPosition( nColumn, nRow ) );
7571
7572 ApplyCellAttributes( pObj, xCell );
7573
7574 if ( ( nRowCount > 1 ) || ( nColumnCount > 1 ) ) // cell merging
7575 {
7576 MergeCells( xTable, nColumn, nRow, nColumnCount, nRowCount );
7577 for ( sal_Int32 nRowIter = 0; nRowIter < nRowCount; nRowIter++ )
7578 {
7579 for ( sal_Int32 nColumnIter = 0; nColumnIter < nColumnCount; nColumnIter++ )
7580 { // now set the correct index for the merged cell
7581 pMergedCellIndexTable[ ( ( nRow + nRowIter ) * aColumns.size() ) + nColumn + nColumnIter ] = nTableIndex;
7582 }
7583 }
7584 }
7585
7586 // applying text
7587 OutlinerParaObject* pParaObject = pObj->GetOutlinerParaObject();
7588 if ( pParaObject )
7589 {
7590 SdrText* pSdrText = pTable->getText( nTableIndex );
7591 if ( pSdrText )
7592 pSdrText->SetOutlinerParaObject(std::make_unique<OutlinerParaObject>(*pParaObject) );
7593 }
7594 }
7595 }
7596 }
7597 aGroupIter.Reset();
7598 while( aGroupIter.IsMore() )
7599 {
7600 SdrObject* pObj( aGroupIter.Next() );
7601 if ( IsLine( pObj ) )
7602 {
7603 std::vector< sal_Int32 > vPositions; // containing cell indexes + cell position
7604 GetLinePositions( pObj, aRows, aColumns, vPositions, pGroup->GetSnapRect() );
7605
7606 // correcting merged cell position
7607 for (auto & vPos : vPositions)
7608 {
7609 sal_Int32 nOldPosition = vPos & 0xffff;
7610 sal_Int32 nOldFlags = vPos & 0xffff0000;
7611 sal_Int32 nNewPosition = pMergedCellIndexTable[ nOldPosition ] | nOldFlags;
7612 vPos = nNewPosition;
7613 }
7614 ApplyCellLineAttributes( pObj, xTable, vPositions, aColumns.size() );
7615 }
7616 }
7617 pMergedCellIndexTable.reset();
7618
7619 // we are replacing the whole group object by a single table object, so
7620 // possibly connections to the group object have to be removed.
7621 if ( pSolverContainer )
7622 {
7623 for (auto & pPtr : pSolverContainer->aCList)
7624 {
7625 // check connections to the group object
7626 if ( pPtr->pAObj == pGroup )
7627 pPtr->pAObj = nullptr;
7628 if ( pPtr->pBObj == pGroup )
7629 pPtr->pBObj = nullptr;
7630
7631 // check connections to all its subobjects
7632 SdrObjListIter aIter( *pGroup, SdrIterMode::DeepWithGroups );
7633 while( aIter.IsMore() )
7634 {
7635 SdrObject* pPartObj = aIter.Next();
7636 if ( pPtr->pAObj == pPartObj )
7637 pPtr->pAObj = nullptr;
7638 if ( pPtr->pBObj == pPartObj )
7639 pPtr->pBObj = nullptr;
7640 }
7641 //In MS, the one_row_one_col table is made up of five
7642 //shape,the connector is connected to some part of a
7643 //table. But for us, the connector is connected to the
7644 //whole group table,so the connector obj is a group
7645 //table when export by us. We should process this
7646 //situation when importing.
7647 if ( pPtr->pAObj == pGroup )
7648 pPtr->pAObj = pTable;
7649 if ( pPtr->pBObj == pGroup )
7650 pPtr->pBObj = pTable;
7651 }
7652 }
7653 pTable->uno_unlock();
7654 pTable->SetSnapRect( pGroup->GetSnapRect() );
7655 pRet = pTable;
7656
7657 //Remove Objects from shape map
7658 SdrObjListIter aIter( *pGroup, SdrIterMode::DeepWithGroups );
7659 while( aIter.IsMore() )
7660 {
7661 SdrObject* pPartObj = aIter.Next();
7662 removeShapeId(pPartObj);
7663 // ofz#41510 make sure rBackgroundColoredObjects doesn't contain deleted objects
7664 std::replace(rBackgroundColoredObjects.begin(), rBackgroundColoredObjects.end(), pPartObj, pRet);
7665 }
7666
7667 SdrObject::Free( pGroup );
7668 }
7669 catch( const Exception& )
7670 {
7671 pTable->uno_unlock();
7672 SdrObject* pObj = pTable;
7673 SdrObject::Free( pObj );
7674 }
7675
7676 return pRet;
7677 }
7678
IsVerticalText() const7679 bool SdrPowerPointImport::IsVerticalText() const
7680 {
7681 bool bVerticalText = false;
7682 if ( IsProperty( DFF_Prop_txflTextFlow ) )
7683 {
7684 auto eTextFlow = GetPropertyValue(DFF_Prop_txflTextFlow, 0) & 0xFFFF;
7685 switch( eTextFlow )
7686 {
7687 case mso_txflTtoBA : // Top to Bottom @-font, above -> below
7688 case mso_txflTtoBN : // Top to Bottom non-@, above -> below
7689 case mso_txflVertN : // Vertical, non-@, above -> below
7690 bVerticalText = !bVerticalText;
7691 break;
7692 default: break;
7693 }
7694 }
7695
7696 return bVerticalText;
7697 }
7698
ApplyTextAnchorAttributes(PPTTextObj const & rTextObj,SfxItemSet & rSet) const7699 void SdrPowerPointImport::ApplyTextAnchorAttributes( PPTTextObj const & rTextObj, SfxItemSet& rSet ) const
7700 {
7701 SdrTextVertAdjust eTVA;
7702 SdrTextHorzAdjust eTHA;
7703
7704 sal_uInt32 nTextFlags = rTextObj.GetTextFlags();
7705
7706 nTextFlags &= PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT
7707 | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK;
7708
7709 if ( IsVerticalText() )
7710 {
7711 eTVA = SDRTEXTVERTADJUST_BLOCK;
7712 eTHA = SDRTEXTHORZADJUST_CENTER;
7713
7714 // read text anchor
7715 auto eTextAnchor = GetPropertyValue(DFF_Prop_anchorText, mso_anchorTop);
7716
7717 switch( eTextAnchor )
7718 {
7719 case mso_anchorTop:
7720 case mso_anchorTopCentered:
7721 eTHA = SDRTEXTHORZADJUST_RIGHT;
7722 break;
7723
7724 case mso_anchorMiddle :
7725 case mso_anchorMiddleCentered:
7726 eTHA = SDRTEXTHORZADJUST_CENTER;
7727 break;
7728
7729 case mso_anchorBottom:
7730 case mso_anchorBottomCentered:
7731 eTHA = SDRTEXTHORZADJUST_LEFT;
7732 break;
7733
7734 default:
7735 break;
7736 }
7737 // if there is a 100% use of following attributes, the textbox can been aligned also in vertical direction
7738 switch ( eTextAnchor )
7739 {
7740 case mso_anchorTopCentered :
7741 case mso_anchorMiddleCentered :
7742 case mso_anchorBottomCentered :
7743 {
7744 // check if it is sensible to use the centered alignment
7745 sal_uInt32 nMask = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT;
7746 if ( ( nTextFlags & nMask ) != nMask ) // if the textobject has left or also right aligned paragraphs
7747 eTVA = SDRTEXTVERTADJUST_CENTER; // the text has to be displayed using the full width;
7748 }
7749 break;
7750
7751 default :
7752 {
7753 if ( nTextFlags == PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT )
7754 eTVA = SDRTEXTVERTADJUST_TOP;
7755 else if ( nTextFlags == PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT )
7756 eTVA = SDRTEXTVERTADJUST_BOTTOM;
7757 }
7758 break;
7759 }
7760 }
7761 else
7762 {
7763 eTVA = SDRTEXTVERTADJUST_CENTER;
7764 eTHA = SDRTEXTHORZADJUST_BLOCK;
7765
7766 // read text anchor
7767 auto eTextAnchor = GetPropertyValue(DFF_Prop_anchorText, mso_anchorTop);
7768
7769 switch( eTextAnchor )
7770 {
7771 case mso_anchorTop:
7772 case mso_anchorTopCentered:
7773 eTVA = SDRTEXTVERTADJUST_TOP;
7774 break;
7775
7776 case mso_anchorMiddle :
7777 case mso_anchorMiddleCentered:
7778 eTVA = SDRTEXTVERTADJUST_CENTER;
7779 break;
7780
7781 case mso_anchorBottom:
7782 case mso_anchorBottomCentered:
7783 eTVA = SDRTEXTVERTADJUST_BOTTOM;
7784 break;
7785
7786 default:
7787 break;
7788 }
7789
7790 // if there is a 100% usage of following attributes, the textbox can be aligned also in horizontal direction
7791 switch ( eTextAnchor )
7792 {
7793 case mso_anchorTopCentered :
7794 case mso_anchorMiddleCentered :
7795 case mso_anchorBottomCentered :
7796 {
7797 // check if it is sensible to use the centered alignment
7798 sal_uInt32 nMask = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT;
7799 if ( ( nTextFlags & nMask ) != nMask ) // if the textobject has left or also right aligned paragraphs
7800 eTHA = SDRTEXTHORZADJUST_CENTER; // the text has to be displayed using the full width;
7801 }
7802 break;
7803
7804 default :
7805 {
7806 if ( nTextFlags == PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT )
7807 eTHA = SDRTEXTHORZADJUST_LEFT;
7808 else if ( nTextFlags == PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT )
7809 eTHA = SDRTEXTHORZADJUST_RIGHT;
7810 }
7811 break;
7812 }
7813 }
7814 rSet.Put( SdrTextVertAdjustItem( eTVA ) );
7815 rSet.Put( SdrTextHorzAdjustItem( eTHA ) );
7816 }
7817
7818 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
7819