Update ooo320-m1
[ooovba.git] / sd / source / filter / ppt / propread.cxx
blobb2cb319c34a605f883b49bf1edeca60afceb71e3
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: propread.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sd.hxx"
33 #include <propread.hxx>
34 #include <tools/bigint.hxx>
35 #include "rtl/tencinfo.h"
36 #include "rtl/textenc.h"
38 // ------------------------------------------------------------------------
40 struct PropEntry
42 sal_uInt32 mnId;
43 sal_uInt32 mnSize;
44 sal_uInt16 mnTextEnc;
45 sal_uInt8* mpBuf;
47 PropEntry( sal_uInt32 nId, const sal_uInt8* pBuf, sal_uInt32 nBufSize, sal_uInt16 nTextEnc );
48 PropEntry( const PropEntry& rProp );
49 ~PropEntry() { delete[] mpBuf; } ;
51 const PropEntry& operator=(const PropEntry& rPropEntry);
54 PropEntry::PropEntry( sal_uInt32 nId, const sal_uInt8* pBuf, sal_uInt32 nBufSize, sal_uInt16 nTextEnc ) :
55 mnId ( nId ),
56 mnSize ( nBufSize ),
57 mnTextEnc ( nTextEnc ),
58 mpBuf ( new sal_uInt8[ nBufSize ] )
60 memcpy( (void*)mpBuf, (void*)pBuf, nBufSize );
63 PropEntry::PropEntry( const PropEntry& rProp ) :
64 mnId ( rProp.mnId ),
65 mnSize ( rProp.mnSize ),
66 mnTextEnc ( rProp.mnTextEnc ),
67 mpBuf ( new sal_uInt8[ mnSize ] )
69 memcpy( (void*)mpBuf, (void*)rProp.mpBuf, mnSize );
72 const PropEntry& PropEntry::operator=(const PropEntry& rPropEntry)
74 if ( this != &rPropEntry )
76 delete[] mpBuf;
77 mnId = rPropEntry.mnId;
78 mnSize = rPropEntry.mnSize;
79 mnTextEnc = rPropEntry.mnTextEnc;
80 mpBuf = new sal_uInt8[ mnSize ];
81 memcpy( (void*)mpBuf, (void*)rPropEntry.mpBuf, mnSize );
83 return *this;
86 // -----------------------------------------------------------------------
88 void PropItem::Clear()
90 Seek( STREAM_SEEK_TO_BEGIN );
91 delete[] (sal_uInt8*)SwitchBuffer();
94 // -----------------------------------------------------------------------
96 BOOL PropItem::Read( String& rString, sal_uInt32 nStringType, sal_Bool bAlign )
98 sal_uInt32 i, nItemSize, nType, nItemPos;
99 sal_Bool bRetValue = sal_False;
101 nItemPos = Tell();
103 if ( nStringType == VT_EMPTY )
104 *this >> nType;
105 else
106 nType = nStringType & VT_TYPEMASK;
108 *this >> nItemSize;
110 switch( nType )
112 case VT_LPSTR :
114 if ( (sal_uInt16)nItemSize )
116 sal_Char* pString = new sal_Char[ (sal_uInt16)nItemSize ];
117 if ( mnTextEnc == RTL_TEXTENCODING_UCS2 )
119 nItemSize >>= 1;
120 if ( (sal_uInt16)nItemSize > 1 )
122 sal_Unicode* pWString = (sal_Unicode*)pString;
123 for ( i = 0; i < (sal_uInt16)nItemSize; i++ )
124 *this >> pWString[ i ];
125 rString = String( pWString, (sal_uInt16)nItemSize - 1 );
127 else
128 rString = String();
129 bRetValue = sal_True;
131 else
133 SvMemoryStream::Read( pString, (sal_uInt16)nItemSize );
134 if ( pString[ (sal_uInt16)nItemSize - 1 ] == 0 )
136 if ( (sal_uInt16)nItemSize > 1 )
137 rString = String( ByteString( pString ), mnTextEnc );
138 else
139 rString = String();
140 bRetValue = sal_True;
143 delete[] pString;
145 if ( bAlign )
146 SeekRel( ( 4 - ( nItemSize & 3 ) ) & 3 ); // dword align
148 break;
150 case VT_LPWSTR :
152 if ( nItemSize )
154 sal_Unicode* pString = new sal_Unicode[ (sal_uInt16)nItemSize ];
155 for ( i = 0; i < (sal_uInt16)nItemSize; i++ )
156 *this >> pString[ i ];
157 if ( pString[ i - 1 ] == 0 )
159 if ( (sal_uInt16)nItemSize > 1 )
160 rString = String( pString, (sal_uInt16)nItemSize - 1 );
161 else
162 rString = String();
163 bRetValue = sal_True;
165 delete[] pString;
167 if ( bAlign && ( nItemSize & 1 ) )
168 SeekRel( 2 ); // dword align
170 break;
172 if ( !bRetValue )
173 Seek( nItemPos );
174 return bRetValue;
177 // -----------------------------------------------------------------------
179 PropItem& PropItem::operator=( PropItem& rPropItem )
181 if ( this != &rPropItem )
183 Seek( STREAM_SEEK_TO_BEGIN );
184 delete[] (sal_uInt8*)SwitchBuffer();
186 mnTextEnc = rPropItem.mnTextEnc;
187 sal_uInt32 nItemPos = rPropItem.Tell();
188 rPropItem.Seek( STREAM_SEEK_TO_END );
189 SvMemoryStream::Write( rPropItem.GetData(), rPropItem.Tell() );
190 rPropItem.Seek( nItemPos );
192 return *this;
195 // -----------------------------------------------------------------------
197 struct Dict
199 sal_uInt32 mnId;
200 String aString;
202 Dict( sal_uInt32 nId, String rString ) { mnId = nId; aString = rString; };
205 // -----------------------------------------------------------------------
207 Dictionary::~Dictionary()
209 for ( void* pPtr = First(); pPtr; pPtr = Next() )
210 delete (Dict*)pPtr;
213 // -----------------------------------------------------------------------
215 void Dictionary::AddProperty( sal_uInt32 nId, const String& rString )
217 if ( rString.Len() ) // eindeutige namen bei properties
219 // pruefen, ob es die Propertybeschreibung in der Dictionary schon gibt
220 for ( Dict* pDict = (Dict*)First(); pDict; pDict = (Dict*)Next() )
222 if ( pDict->mnId == nId )
224 pDict->aString = rString;
225 return;
228 Insert( new Dict( nId, rString ), LIST_APPEND );
232 // -----------------------------------------------------------------------
234 UINT32 Dictionary::GetProperty( const String& rString )
236 for ( Dict* pDict = (Dict*)First(); pDict; pDict = (Dict*)Next() )
238 if ( pDict->aString == rString )
239 return pDict->mnId;
241 return 0;
244 // -----------------------------------------------------------------------
246 Dictionary& Dictionary::operator=( Dictionary& rDictionary )
248 void* pPtr;
250 if ( this != &rDictionary )
252 for ( pPtr = First(); pPtr; pPtr = Next() )
253 delete (Dict*)pPtr;
255 for ( pPtr = rDictionary.First(); pPtr; pPtr = rDictionary.Next() )
256 Insert( new Dict( ((Dict*)pPtr)->mnId, ((Dict*)pPtr)->aString ), LIST_APPEND );
258 return *this;
261 // -----------------------------------------------------------------------
263 Section::Section( Section& rSection )
264 : List()
266 mnTextEnc = rSection.mnTextEnc;
267 for ( int i = 0; i < 16; i++ )
268 aFMTID[ i ] = rSection.aFMTID[ i ];
269 for ( PropEntry* pProp = (PropEntry*)rSection.First(); pProp; pProp = (PropEntry*)rSection.Next() )
270 Insert( new PropEntry( *pProp ), LIST_APPEND );
273 // -----------------------------------------------------------------------
275 Section::Section( const sal_uInt8* pFMTID )
277 mnTextEnc = RTL_TEXTENCODING_MS_1252;
278 for ( int i = 0; i < 16; i++ )
279 aFMTID[ i ] = pFMTID[ i ];
282 // -----------------------------------------------------------------------
284 sal_Bool Section::GetProperty( sal_uInt32 nId, PropItem& rPropItem )
286 PropEntry* pProp;
287 if ( nId )
289 for ( pProp = (PropEntry*)First(); pProp; pProp = (PropEntry*)Next() )
291 if ( pProp->mnId == nId )
292 break;
294 if ( pProp )
296 rPropItem.Clear();
297 rPropItem.SetTextEncoding( mnTextEnc );
298 rPropItem.Write( pProp->mpBuf, pProp->mnSize );
299 rPropItem.Seek( STREAM_SEEK_TO_BEGIN );
300 return sal_True;
303 return sal_False;
306 // -----------------------------------------------------------------------
308 void Section::AddProperty( sal_uInt32 nId, const sal_uInt8* pBuf, sal_uInt32 nBufSize )
310 // kleiner id check
312 if ( !nId )
313 return;
314 if ( nId == 0xffffffff )
315 nId = 0;
317 // keine doppelten PropId's zulassen, sortieren
318 for ( sal_uInt32 i = 0; i < Count(); i++ )
320 PropEntry* pPropEntry = (PropEntry*)GetObject( i );
321 if ( pPropEntry->mnId == nId )
322 delete (PropEntry*)Replace( new PropEntry( nId, pBuf, nBufSize, mnTextEnc ), i );
323 else if ( pPropEntry->mnId > nId )
324 Insert( new PropEntry( nId, pBuf, nBufSize, mnTextEnc ), i );
325 else
326 continue;
327 return;
329 Insert( new PropEntry( nId, pBuf, nBufSize, mnTextEnc ), LIST_APPEND );
332 // -----------------------------------------------------------------------
334 sal_Bool Section::GetDictionary( Dictionary& rDict )
336 sal_Bool bRetValue = sal_False;
338 Dictionary aDict;
339 PropEntry* pProp;
341 for ( pProp = (PropEntry*)First(); pProp; pProp = (PropEntry*)Next() )
343 if ( pProp->mnId == 0 )
344 break;
346 if ( pProp )
348 sal_uInt32 nDictCount, nId, nSize, nPos;
349 SvMemoryStream aStream( (sal_Int8*)pProp->mpBuf, pProp->mnSize, STREAM_READ );
350 aStream.Seek( STREAM_SEEK_TO_BEGIN );
351 aStream >> nDictCount;
352 for ( sal_uInt32 i = 0; i < nDictCount; i++ )
354 aStream >> nId >> nSize;
355 if ( (sal_uInt16)nSize )
357 String aString;
358 nPos = aStream.Tell();
359 sal_Char* pString = new sal_Char[ (sal_uInt16)nSize ];
360 aStream.Read( pString, (sal_uInt16)nSize );
361 if ( mnTextEnc == RTL_TEXTENCODING_UCS2 )
363 nSize >>= 1;
364 aStream.Seek( nPos );
365 sal_Unicode* pWString = (sal_Unicode*)pString;
366 for ( i = 0; i < (sal_uInt16)nSize; i++ )
367 aStream >> pWString[ i ];
368 aString = String( pWString, (sal_uInt16)nSize - 1 );
370 else
371 aString = String( ByteString( pString, (sal_uInt16)nSize - 1 ), mnTextEnc );
372 delete[] pString;
373 if ( !aString.Len() )
374 break;
375 aDict.AddProperty( nId, aString );
377 bRetValue = sal_True;
380 rDict = aDict;
381 return bRetValue;
384 // -----------------------------------------------------------------------
386 Section::~Section()
388 for ( PropEntry* pProp = (PropEntry*)First(); pProp; pProp = (PropEntry*)Next() )
389 delete pProp;
392 // -----------------------------------------------------------------------
394 void Section::Read( SvStorageStream *pStrm )
396 sal_uInt32 i, nSecOfs, nSecSize, nPropCount, nPropId, nPropOfs, nPropType, nPropSize, nCurrent, nVectorCount, nTemp, nStrmSize;
397 nSecOfs = pStrm->Tell();
399 pStrm->Seek( STREAM_SEEK_TO_END );
400 nStrmSize = pStrm->Tell();
401 pStrm->Seek( nSecOfs );
403 mnTextEnc = RTL_TEXTENCODING_MS_1252;
404 *pStrm >> nSecSize >> nPropCount;
405 while( nPropCount-- && ( pStrm->GetError() == ERRCODE_NONE ) )
407 *pStrm >> nPropId >> nPropOfs;
408 nCurrent = pStrm->Tell();
409 pStrm->Seek( nPropOfs + nSecOfs );
410 if ( nPropId ) // dictionary wird nicht eingelesen
413 *pStrm >> nPropType;
415 nPropSize = 4;
417 if ( nPropType & VT_VECTOR )
419 *pStrm >> nVectorCount;
420 nPropType &=~VT_VECTOR;
421 nPropSize += 4;
423 else
424 nVectorCount = 1;
427 sal_Bool bVariant = ( nPropType == VT_VARIANT );
429 for ( i = 0; nPropSize && ( i < nVectorCount ); i++ )
431 if ( bVariant )
433 *pStrm >> nPropType;
434 nPropSize += 4;
436 switch( nPropType )
438 case VT_UI1 :
439 nPropSize++;
440 break;
442 case VT_I2 :
443 case VT_UI2 :
444 case VT_BOOL :
445 nPropSize += 2;
446 break;
448 case VT_I4 :
449 case VT_R4 :
450 case VT_UI4 :
451 case VT_ERROR :
452 nPropSize += 4;
453 break;
455 case VT_I8 :
456 case VT_R8 :
457 case VT_CY :
458 case VT_UI8 :
459 case VT_DATE :
460 case VT_FILETIME :
461 nPropSize += 8;
462 break;
464 case VT_BSTR :
465 *pStrm >> nTemp;
466 nPropSize += ( nTemp + 4 );
467 break;
469 case VT_LPSTR :
470 *pStrm >> nTemp;
471 nPropSize += ( nTemp + 4 );
472 break;
474 case VT_LPWSTR :
475 *pStrm >> nTemp;
476 nPropSize += ( nTemp << 1 ) + 4;
477 break;
479 case VT_BLOB_OBJECT :
480 case VT_BLOB :
481 case VT_CF :
482 *pStrm >> nTemp;
483 nPropSize += ( nTemp + 4 );
484 break;
486 case VT_CLSID :
487 case VT_STREAM :
488 case VT_STORAGE :
489 case VT_STREAMED_OBJECT :
490 case VT_STORED_OBJECT :
491 case VT_VARIANT :
492 case VT_VECTOR :
493 default :
494 nPropSize = 0;
496 if ( nPropSize )
498 if ( ( nVectorCount - i ) > 1 )
499 pStrm->Seek( nPropOfs + nSecOfs + nPropSize );
501 else
502 break;
504 if ( nPropSize )
506 pStrm->Seek( nPropOfs + nSecOfs );
507 sal_uInt8* pBuf = new sal_uInt8[ nPropSize ];
508 pStrm->Read( pBuf, nPropSize );
509 AddProperty( nPropId, pBuf, nPropSize );
510 delete[] pBuf;
512 if ( nPropId == 1 )
514 PropItem aPropItem;
515 if ( GetProperty( 1, aPropItem ) )
517 sal_uInt16 nCodePage;
518 aPropItem >> nPropType;
519 if ( nPropType == VT_I2 )
521 aPropItem >> nCodePage;
523 if ( nCodePage == 1200 )
525 mnTextEnc = RTL_TEXTENCODING_UCS2;
527 else
529 mnTextEnc = rtl_getTextEncodingFromWindowsCodePage( nCodePage );
530 if ( mnTextEnc == RTL_TEXTENCODING_DONTKNOW )
531 mnTextEnc = RTL_TEXTENCODING_MS_1252;
534 else
536 mnTextEnc = RTL_TEXTENCODING_MS_1252;
541 else
543 sal_uInt32 nDictCount, nSize;
544 *pStrm >> nDictCount;
545 for ( i = 0; i < nDictCount; i++ )
547 *pStrm >> nSize >> nSize;
548 pStrm->SeekRel( nSize );
550 nSize = pStrm->Tell();
551 pStrm->Seek( nPropOfs + nSecOfs );
552 nSize -= pStrm->Tell();
553 if ( nSize > nStrmSize )
555 nPropCount = 0;
556 break;
558 sal_uInt8* pBuf = new sal_uInt8[ nSize ];
559 pStrm->Read( pBuf, nSize );
560 AddProperty( 0xffffffff, pBuf, nSize );
561 delete[] pBuf;
563 pStrm->Seek( nCurrent );
565 pStrm->Seek( nSecOfs + nSecSize );
568 // -----------------------------------------------------------------------
570 Section& Section::operator=( Section& rSection )
572 PropEntry* pProp;
574 if ( this != &rSection )
576 memcpy( (void*)aFMTID, (void*)rSection.aFMTID, 16 );
577 for ( pProp = (PropEntry*)First(); pProp; pProp = (PropEntry*)Next() )
578 delete pProp;
579 Clear();
580 for ( pProp = (PropEntry*)rSection.First(); pProp; pProp = (PropEntry*)rSection.Next() )
581 Insert( new PropEntry( *pProp ), LIST_APPEND );
583 return *this;
586 // -----------------------------------------------------------------------
588 PropRead::PropRead( SvStorage& rStorage, const String& rName ) :
589 mbStatus ( sal_False ),
590 mnByteOrder ( 0xfffe ),
591 mnFormat ( 0 ),
592 mnVersionLo ( 4 ),
593 mnVersionHi ( 2 )
595 if ( rStorage.IsStream( rName ) )
597 mpSvStream = rStorage.OpenSotStream( rName, STREAM_STD_READ );
598 if ( mpSvStream )
600 mpSvStream->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
601 memset( mApplicationCLSID, 0, 16 );
602 mbStatus = sal_True;
607 // -----------------------------------------------------------------------
609 void PropRead::AddSection( Section& rSection )
611 Insert( new Section( rSection ), LIST_APPEND );
614 // -----------------------------------------------------------------------
616 const Section* PropRead::GetSection( const sal_uInt8* pFMTID )
618 Section* pSection;
620 for ( pSection = (Section*)First(); pSection; pSection = (Section*)Next() )
622 if ( memcmp( pSection->GetFMTID(), pFMTID, 16 ) == 0 )
623 break;
625 return pSection;
628 // -----------------------------------------------------------------------
630 PropRead::~PropRead()
632 for ( Section* pSection = (Section*)First(); pSection; pSection = (Section*)Next() )
633 delete pSection;
636 // -----------------------------------------------------------------------
638 void PropRead::Read()
640 for ( Section* pSection = (Section*)First(); pSection; pSection = (Section*)Next() )
641 delete pSection;
642 Clear();
643 if ( mbStatus )
645 sal_uInt32 nSections;
646 sal_uInt32 nSectionOfs;
647 sal_uInt32 nCurrent;
648 *mpSvStream >> mnByteOrder >> mnFormat >> mnVersionLo >> mnVersionHi;
649 if ( mnByteOrder == 0xfffe )
651 sal_uInt8* pSectCLSID = new sal_uInt8[ 16 ];
652 mpSvStream->Read( mApplicationCLSID, 16 );
653 *mpSvStream >> nSections;
654 if ( nSections > 2 ) // sj: PowerPoint documents are containing max 2 sections
656 mbStatus = sal_False;
658 else for ( sal_uInt32 i = 0; i < nSections; i++ )
660 mpSvStream->Read( pSectCLSID, 16 );
661 *mpSvStream >> nSectionOfs;
662 nCurrent = mpSvStream->Tell();
663 mpSvStream->Seek( nSectionOfs );
664 Section aSection( pSectCLSID );
665 aSection.Read( mpSvStream );
666 AddSection( aSection );
667 mpSvStream->Seek( nCurrent );
669 delete[] pSectCLSID;
674 // -----------------------------------------------------------------------
676 PropRead& PropRead::operator=( PropRead& rPropRead )
678 Section* pSection;
680 if ( this != &rPropRead )
682 mbStatus = rPropRead.mbStatus;
683 mpSvStream = rPropRead.mpSvStream;
685 mnByteOrder = rPropRead.mnByteOrder;
686 mnFormat = rPropRead.mnFormat;
687 mnVersionLo = rPropRead.mnVersionLo;
688 mnVersionHi = rPropRead.mnVersionHi;
689 memcpy( mApplicationCLSID, rPropRead.mApplicationCLSID, 16 );
691 for ( pSection = (Section*)First(); pSection; pSection = (Section*)Next() )
692 delete pSection;
693 Clear();
694 for ( pSection = (Section*)rPropRead.First(); pSection; pSection = (Section*)rPropRead.Next() )
695 Insert( new Section( *pSection ), LIST_APPEND );
697 return *this;