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