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