1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: image.cxx,v $
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_basic.hxx"
33 #include <tools/stream.hxx>
34 #include <tools/tenccvt.hxx>
35 #include <basic/sbx.hxx>
37 #include <string.h> // memset() etc
39 #include <codegen.hxx>
55 eCharSet
= gsl_getSystemTextEncoding();
63 void SbiImage::Clear()
68 ReleaseLegacyBuffer();
77 eCharSet
= gsl_getSystemTextEncoding();
82 /**************************************************************************
84 * Service-Routines for Load/Store
86 **************************************************************************/
88 BOOL
SbiGood( SvStream
& r
)
90 return BOOL( !r
.IsEof() && r
.GetError() == SVSTREAM_OK
);
94 ULONG
SbiOpenRecord( SvStream
& r
, UINT16 nSignature
, UINT16 nElem
)
96 ULONG nPos
= r
.Tell();
97 r
<< nSignature
<< (INT32
) 0 << nElem
;
102 void SbiCloseRecord( SvStream
& r
, ULONG nOff
)
104 ULONG nPos
= r
.Tell();
106 r
<< (INT32
) ( nPos
- nOff
- 8 );
110 /**************************************************************************
114 **************************************************************************/
116 // If the version number does not find, binary parts are omitted, but not
117 // source, comments and name
118 BOOL
SbiImage::Load( SvStream
& r
)
120 UINT32 nVersion
= 0; // Versionsnumber
121 return Load( r
, nVersion
);
123 BOOL
SbiImage::Load( SvStream
& r
, UINT32
& nVersion
)
126 UINT16 nSign
, nCount
;
130 // Read Master-Record
131 r
>> nSign
>> nLen
>> nCount
;
132 ULONG nLast
= r
.Tell() + nLen
;
133 UINT32 nCharSet
; // System charset
138 BOOL bBadVer
= FALSE
;
139 if( nSign
== B_MODULE
)
141 r
>> nVersion
>> nCharSet
>> lDimBase
142 >> nFlags
>> nReserved1
>> nReserved2
>> nReserved3
;
143 eCharSet
= (CharSet
) nCharSet
;
144 eCharSet
= GetSOLoadTextEncoding( eCharSet
);
145 bBadVer
= BOOL( nVersion
> B_CURVERSION
);
146 nDimBase
= (USHORT
) lDimBase
;
149 bool bLegacy
= ( nVersion
< B_EXT_IMG_VERSION
);
152 while( ( nNext
= r
.Tell() ) < nLast
)
156 r
>> nSign
>> nLen
>> nCount
;
158 if( r
.GetError() == SVSTREAM_OK
)
162 r
.ReadByteString( aName
, eCharSet
);
166 r
.ReadByteString( aComment
, eCharSet
);
172 r
.ReadByteString( aTmp
, eCharSet
);
177 #ifdef EXTENDED_BINARY_MODULES
180 for( UINT16 j
= 0 ; j
< nCount
; j
++ )
183 r
.ReadByteString( aTmp
, eCharSet
);
191 pCode
= new char[ nLen
];
193 r
.Read( pCode
, nCodeSize
);
196 ReleaseLegacyBuffer(); // release any previously held buffer
197 nLegacyCodeSize
= (UINT16
) nCodeSize
;
198 pLegacyPCode
= pCode
;
200 PCodeBuffConvertor
< UINT16
, UINT32
> aLegacyToNew( (BYTE
*)pLegacyPCode
, nLegacyCodeSize
);
201 aLegacyToNew
.convert();
202 pCode
= (char*)aLegacyToNew
.GetBuffer();
203 nCodeSize
= aLegacyToNew
.GetSize();
204 // we don't release the legacy buffer
205 // right now, thats because the module
206 // needs it to fix up the method
207 // nStart members. When that is done
208 // the module can release the buffer
209 // or it can wait until this routine
210 // is called again or when this class // destructs all of which will trigger
211 // release of the buffer.
221 MakeStrings( nCount
);
222 for( i
= 0; i
< nStrings
&& SbiGood( r
); i
++ )
225 pStringOff
[ i
] = (USHORT
) nOff
;
231 pStrings
= new sal_Unicode
[ nLen
];
232 nStringSize
= (USHORT
) nLen
;
234 char* pByteStrings
= new char[ nLen
];
235 r
.Read( pByteStrings
, nStringSize
);
236 for( short j
= 0; j
< nStrings
; j
++ )
238 USHORT nOff2
= (USHORT
) pStringOff
[ j
];
239 String
aStr( pByteStrings
+ nOff2
, eCharSet
);
240 memcpy( pStrings
+ nOff2
, aStr
.GetBuffer(), (aStr
.Len() + 1) * sizeof( sal_Unicode
) );
242 delete[] pByteStrings
;
255 //if( eCharSet != ::GetSystemCharSet() )
259 return BOOL( !bError
);
262 BOOL
SbiImage::Save( SvStream
& r
, UINT32 nVer
)
264 bool bLegacy
= ( nVer
< B_EXT_IMG_VERSION
);
266 // detect if old code exceeds legacy limits
267 // if so, then disallow save
268 if ( bLegacy
&& ExceedsLegacyLimits() )
271 aEmptyImg
.aName
= aName
;
272 aEmptyImg
.Save( r
, B_LEGACYVERSION
);
275 // First of all the header
276 ULONG nStart
= SbiOpenRecord( r
, B_MODULE
, 1 );
279 eCharSet
= GetSOStoreTextEncoding( eCharSet
);
281 r
<< (INT32
) B_LEGACYVERSION
;
283 r
<< (INT32
) B_CURVERSION
;
284 r
<< (INT32
) eCharSet
292 if( aName
.Len() && SbiGood( r
) )
294 nPos
= SbiOpenRecord( r
, B_NAME
, 1 );
295 r
.WriteByteString( aName
, eCharSet
);
297 SbiCloseRecord( r
, nPos
);
300 if( aComment
.Len() && SbiGood( r
) )
302 nPos
= SbiOpenRecord( r
, B_COMMENT
, 1 );
303 r
.WriteByteString( aComment
, eCharSet
);
305 SbiCloseRecord( r
, nPos
);
308 if( aOUSource
.getLength() && SbiGood( r
) )
310 nPos
= SbiOpenRecord( r
, B_SOURCE
, 1 );
312 sal_Int32 nLen
= aOUSource
.getLength();
313 const sal_Int32 nMaxUnitSize
= STRING_MAXLEN
- 1;
314 if( nLen
> STRING_MAXLEN
)
315 aTmp
= aOUSource
.copy( 0, nMaxUnitSize
);
318 r
.WriteByteString( aTmp
, eCharSet
);
320 SbiCloseRecord( r
, nPos
);
322 #ifdef EXTENDED_BINARY_MODULES
323 if( nLen
> STRING_MAXLEN
)
325 sal_Int32 nRemainingLen
= nLen
- nMaxUnitSize
;
326 UINT16 nUnitCount
= UINT16( (nRemainingLen
+ nMaxUnitSize
- 1) / nMaxUnitSize
);
327 nPos
= SbiOpenRecord( r
, B_EXTSOURCE
, nUnitCount
);
328 for( UINT16 i
= 0 ; i
< nUnitCount
; i
++ )
331 (nRemainingLen
> nMaxUnitSize
) ? nMaxUnitSize
: nRemainingLen
;
332 String aTmp2
= aOUSource
.copy( (i
+1) * nMaxUnitSize
, nCopyLen
);
333 nRemainingLen
-= nCopyLen
;
334 r
.WriteByteString( aTmp2
, eCharSet
);
336 SbiCloseRecord( r
, nPos
);
341 if( pCode
&& SbiGood( r
) )
343 nPos
= SbiOpenRecord( r
, B_PCODE
, 1 );
346 ReleaseLegacyBuffer(); // release any previously held buffer
347 PCodeBuffConvertor
< UINT32
, UINT16
> aNewToLegacy( (BYTE
*)pCode
, nCodeSize
);
348 aNewToLegacy
.convert();
349 pLegacyPCode
= (char*)aNewToLegacy
.GetBuffer();
350 nLegacyCodeSize
= aNewToLegacy
.GetSize();
351 r
.Write( pLegacyPCode
, nLegacyCodeSize
);
354 r
.Write( pCode
, nCodeSize
);
355 SbiCloseRecord( r
, nPos
);
360 nPos
= SbiOpenRecord( r
, B_STRINGPOOL
, nStrings
);
362 // UINT32 Offset of the Strings in the Stringblock
365 for( i
= 0; i
< nStrings
&& SbiGood( r
); i
++ )
366 r
<< (UINT32
) pStringOff
[ i
];
368 // Then the String-Block
369 char* pByteStrings
= new char[ nStringSize
];
370 for( i
= 0; i
< nStrings
; i
++ )
372 USHORT nOff
= (USHORT
) pStringOff
[ i
];
373 ByteString
aStr( pStrings
+ nOff
, eCharSet
);
374 memcpy( pByteStrings
+ nOff
, aStr
.GetBuffer(), (aStr
.Len() + 1) * sizeof( char ) );
376 r
<< (UINT32
) nStringSize
;
377 r
.Write( pByteStrings
, nStringSize
);
379 delete[] pByteStrings
;
380 SbiCloseRecord( r
, nPos
);
382 // Set overall length
383 SbiCloseRecord( r
, nStart
);
386 return BOOL( !bError
);
389 /**************************************************************************
391 * Routines called by the compiler
393 **************************************************************************/
395 void SbiImage::MakeStrings( short nSize
)
401 pStrings
= new sal_Unicode
[ nStringSize
];
402 pStringOff
= new UINT32
[ nSize
];
403 if( pStrings
&& pStringOff
)
406 memset( pStringOff
, 0, nSize
* sizeof( UINT32
) );
407 memset( pStrings
, 0, nStringSize
* sizeof( sal_Unicode
) );
413 // Hinzufuegen eines Strings an den StringPool. Der String-Puffer
414 // waechst dynamisch in 1K-Schritten
415 // Add a string to StringPool. The String buffer is dynamically
416 // growing in 1K-Steps
417 void SbiImage::AddString( const String
& r
)
419 if( nStringIdx
>= nStrings
)
423 xub_StrLen len
= r
.Len() + 1;
424 UINT32 needed
= nStringOff
+ len
;
425 if( needed
> 0xFFFFFF00L
)
426 bError
= TRUE
; // out of mem!
427 else if( needed
> nStringSize
)
429 UINT32 nNewLen
= needed
+ 1024;
430 nNewLen
&= 0xFFFFFC00; // trim to 1K border
431 if( nNewLen
> 0xFFFFFF00L
)
432 nNewLen
= 0xFFFFFF00L
;
433 sal_Unicode
* p
= NULL
;
434 if( (p
= new sal_Unicode
[ nNewLen
]) != NULL
)
436 memcpy( p
, pStrings
, nStringSize
* sizeof( sal_Unicode
) );
439 nStringSize
= sal::static_int_cast
< UINT16
>(nNewLen
);
446 pStringOff
[ nStringIdx
++ ] = nStringOff
;
447 //ByteString aByteStr( r, eCharSet );
448 memcpy( pStrings
+ nStringOff
, r
.GetBuffer(), len
* sizeof( sal_Unicode
) );
449 nStringOff
= nStringOff
+ len
;
450 // Last String? The update the size of the buffer
451 if( nStringIdx
>= nStrings
)
452 nStringSize
= nStringOff
;
458 // The block was fetched by the compiler from class SbBuffer and
459 // is already created with new. Additionally it contains all Integers
460 // in Big Endian format, so can be directly read/written.
461 void SbiImage::AddCode( char* p
, UINT32 s
)
468 void SbiImage::AddType(SbxObject
* pObject
)
471 rTypes
= new SbxArray
;
472 SbxObject
*pCopyObject
= new SbxObject(*pObject
);
473 rTypes
->Insert (pCopyObject
,rTypes
->Count());
476 void SbiImage::AddEnum(SbxObject
* pObject
) // Register enum type
479 rEnums
= new SbxArray
;
480 rEnums
->Insert( pObject
, rEnums
->Count() );
484 /**************************************************************************
486 * Accessing the image
488 **************************************************************************/
490 // Note: IDs start with 1
491 String
SbiImage::GetString( short nId
) const
493 if( nId
&& nId
<= nStrings
)
495 UINT32 nOff
= pStringOff
[ nId
- 1 ];
496 sal_Unicode
* pStr
= pStrings
+ nOff
;
498 // #i42467: Special treatment for vbNullChar
501 UINT32 nNextOff
= (nId
< nStrings
) ? pStringOff
[ nId
] : nStringOff
;
502 UINT32 nLen
= nNextOff
- nOff
- 1;
505 // Force length 1 and make char 0 afterwards
506 String
aNullCharStr( String::CreateFromAscii( " " ) );
507 aNullCharStr
.SetChar( 0, 0 );
520 const SbxObject
* SbiImage::FindType (String aTypeName
) const
522 return rTypes
.Is() ? (SbxObject
*)rTypes
->Find(aTypeName
,SbxCLASS_OBJECT
) : NULL
;
525 UINT16
SbiImage::CalcLegacyOffset( INT32 nOffset
)
527 return SbiCodeGen::calcLegacyOffSet( (BYTE
*)pCode
, nOffset
) ;
530 UINT32
SbiImage::CalcNewOffset( INT16 nOffset
)
532 return SbiCodeGen::calcNewOffSet( (BYTE
*)pLegacyPCode
, nOffset
) ;
535 void SbiImage::ReleaseLegacyBuffer()
537 delete[] pLegacyPCode
;
542 BOOL
SbiImage::ExceedsLegacyLimits()
544 if ( ( nStringSize
> 0xFF00L
) || ( CalcLegacyOffset( nCodeSize
) > 0xFF00L
) )