merge the formfield patch from ooo-build
[ooovba.git] / basic / source / classes / image.cxx
blobd799050724d5cc6b6e3cdfb2e2536512025fc2fb
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: image.cxx,v $
10 * $Revision: 1.25 $
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>
36 #include "sb.hxx"
37 #include <string.h> // memset() etc
38 #include "image.hxx"
39 #include <codegen.hxx>
40 SbiImage::SbiImage()
42 pStringOff = NULL;
43 pStrings = NULL;
44 pCode = NULL;
45 pLegacyPCode = NULL;
46 nFlags = 0;
47 nStrings = 0;
48 nStringSize= 0;
49 nCodeSize = 0;
50 nLegacyCodeSize =
51 nDimBase = 0;
52 bInit =
53 bError = FALSE;
54 bFirstInit = TRUE;
55 eCharSet = gsl_getSystemTextEncoding();
58 SbiImage::~SbiImage()
60 Clear();
63 void SbiImage::Clear()
65 delete[] pStringOff;
66 delete[] pStrings;
67 delete[] pCode;
68 ReleaseLegacyBuffer();
69 pStringOff = NULL;
70 pStrings = NULL;
71 pCode = NULL;
72 nFlags = 0;
73 nStrings = 0;
74 nStringSize= 0;
75 nLegacyCodeSize = 0;
76 nCodeSize = 0;
77 eCharSet = gsl_getSystemTextEncoding();
78 nDimBase = 0;
79 bError = FALSE;
82 /**************************************************************************
84 * Service-Routines for Load/Store
86 **************************************************************************/
88 BOOL SbiGood( SvStream& r )
90 return BOOL( !r.IsEof() && r.GetError() == SVSTREAM_OK );
93 // Open Record
94 ULONG SbiOpenRecord( SvStream& r, UINT16 nSignature, UINT16 nElem )
96 ULONG nPos = r.Tell();
97 r << nSignature << (INT32) 0 << nElem;
98 return nPos;
101 // Close Record
102 void SbiCloseRecord( SvStream& r, ULONG nOff )
104 ULONG nPos = r.Tell();
105 r.Seek( nOff + 2 );
106 r << (INT32) ( nPos - nOff - 8 );
107 r.Seek( nPos );
110 /**************************************************************************
112 * Load/Store
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;
127 UINT32 nLen, nOff;
129 Clear();
130 // Read Master-Record
131 r >> nSign >> nLen >> nCount;
132 ULONG nLast = r.Tell() + nLen;
133 UINT32 nCharSet; // System charset
134 UINT32 lDimBase;
135 UINT16 nReserved1;
136 UINT32 nReserved2;
137 UINT32 nReserved3;
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 );
151 ULONG nNext;
152 while( ( nNext = r.Tell() ) < nLast )
154 short i;
156 r >> nSign >> nLen >> nCount;
157 nNext += nLen + 8;
158 if( r.GetError() == SVSTREAM_OK )
159 switch( nSign )
161 case B_NAME:
162 r.ReadByteString( aName, eCharSet );
163 //r >> aName;
164 break;
165 case B_COMMENT:
166 r.ReadByteString( aComment, eCharSet );
167 //r >> aComment;
168 break;
169 case B_SOURCE:
171 String aTmp;
172 r.ReadByteString( aTmp, eCharSet );
173 aOUSource = aTmp;
174 //r >> aSource;
175 break;
177 #ifdef EXTENDED_BINARY_MODULES
178 case B_EXTSOURCE:
180 for( UINT16 j = 0 ; j < nCount ; j++ )
182 String aTmp;
183 r.ReadByteString( aTmp, eCharSet );
184 aOUSource += aTmp;
186 break;
188 #endif
189 case B_PCODE:
190 if( bBadVer ) break;
191 pCode = new char[ nLen ];
192 nCodeSize = nLen;
193 r.Read( pCode, nCodeSize );
194 if ( bLegacy )
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.
213 break;
214 case B_PUBLICS:
215 case B_POOLDIR:
216 case B_SYMPOOL:
217 case B_LINERANGES:
218 break;
219 case B_STRINGPOOL:
220 if( bBadVer ) break;
221 MakeStrings( nCount );
222 for( i = 0; i < nStrings && SbiGood( r ); i++ )
224 r >> nOff;
225 pStringOff[ i ] = (USHORT) nOff;
227 r >> nLen;
228 if( SbiGood( r ) )
230 delete [] pStrings;
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;
243 } break;
244 case B_MODEND:
245 goto done;
246 default:
247 break;
249 else
250 break;
251 r.Seek( nNext );
253 done:
254 r.Seek( nLast );
255 //if( eCharSet != ::GetSystemCharSet() )
256 //ConvertStrings();
257 if( !SbiGood( r ) )
258 bError = TRUE;
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() )
270 SbiImage aEmptyImg;
271 aEmptyImg.aName = aName;
272 aEmptyImg.Save( r, B_LEGACYVERSION );
273 return TRUE;
275 // First of all the header
276 ULONG nStart = SbiOpenRecord( r, B_MODULE, 1 );
277 ULONG nPos;
279 eCharSet = GetSOStoreTextEncoding( eCharSet );
280 if ( bLegacy )
281 r << (INT32) B_LEGACYVERSION;
282 else
283 r << (INT32) B_CURVERSION;
284 r << (INT32) eCharSet
285 << (INT32) nDimBase
286 << (INT16) nFlags
287 << (INT16) 0
288 << (INT32) 0
289 << (INT32) 0;
291 // Name?
292 if( aName.Len() && SbiGood( r ) )
294 nPos = SbiOpenRecord( r, B_NAME, 1 );
295 r.WriteByteString( aName, eCharSet );
296 //r << aName;
297 SbiCloseRecord( r, nPos );
299 // Comment?
300 if( aComment.Len() && SbiGood( r ) )
302 nPos = SbiOpenRecord( r, B_COMMENT, 1 );
303 r.WriteByteString( aComment, eCharSet );
304 //r << aComment;
305 SbiCloseRecord( r, nPos );
307 // Source?
308 if( aOUSource.getLength() && SbiGood( r ) )
310 nPos = SbiOpenRecord( r, B_SOURCE, 1 );
311 String aTmp;
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 );
316 else
317 aTmp = aOUSource;
318 r.WriteByteString( aTmp, eCharSet );
319 //r << aSource;
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++ )
330 sal_Int32 nCopyLen =
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 );
338 #endif
340 // Binary data?
341 if( pCode && SbiGood( r ) )
343 nPos = SbiOpenRecord( r, B_PCODE, 1 );
344 if ( bLegacy )
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 );
353 else
354 r.Write( pCode, nCodeSize );
355 SbiCloseRecord( r, nPos );
357 // String-Pool?
358 if( nStrings )
360 nPos = SbiOpenRecord( r, B_STRINGPOOL, nStrings );
361 // For every String:
362 // UINT32 Offset of the Strings in the Stringblock
363 short i;
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 );
384 if( !SbiGood( r ) )
385 bError = TRUE;
386 return BOOL( !bError );
389 /**************************************************************************
391 * Routines called by the compiler
393 **************************************************************************/
395 void SbiImage::MakeStrings( short nSize )
397 nStrings = 0;
398 nStringIdx = 0;
399 nStringOff = 0;
400 nStringSize = 1024;
401 pStrings = new sal_Unicode[ nStringSize ];
402 pStringOff = new UINT32[ nSize ];
403 if( pStrings && pStringOff )
405 nStrings = nSize;
406 memset( pStringOff, 0, nSize * sizeof( UINT32 ) );
407 memset( pStrings, 0, nStringSize * sizeof( sal_Unicode ) );
409 else
410 bError = TRUE;
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 )
420 bError = TRUE;
421 if( !bError )
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 ) );
437 delete[] pStrings;
438 pStrings = p;
439 nStringSize = sal::static_int_cast< UINT16 >(nNewLen);
441 else
442 bError = TRUE;
444 if( !bError )
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;
457 // Add code block
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 )
463 pCode = p;
464 nCodeSize = s;
467 // Add user type
468 void SbiImage::AddType(SbxObject* pObject)
470 if( !rTypes.Is() )
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
478 if( !rEnums.Is() )
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
499 if( *pStr == 0 )
501 UINT32 nNextOff = (nId < nStrings) ? pStringOff[ nId ] : nStringOff;
502 UINT32 nLen = nNextOff - nOff - 1;
503 if( nLen == 1 )
505 // Force length 1 and make char 0 afterwards
506 String aNullCharStr( String::CreateFromAscii( " " ) );
507 aNullCharStr.SetChar( 0, 0 );
508 return aNullCharStr;
511 else
513 String aStr( pStr );
514 return aStr;
517 return String();
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;
538 pLegacyPCode = NULL;
539 nLegacyCodeSize = 0;
542 BOOL SbiImage::ExceedsLegacyLimits()
544 if ( ( nStringSize > 0xFF00L ) || ( CalcLegacyOffset( nCodeSize ) > 0xFF00L ) )
545 return TRUE;
546 return FALSE;