diff options
Diffstat (limited to 'basic/source/classes/image.cxx')
-rw-r--r-- | basic/source/classes/image.cxx | 544 |
1 files changed, 544 insertions, 0 deletions
diff --git a/basic/source/classes/image.cxx b/basic/source/classes/image.cxx new file mode 100644 index 000000000000..79f49eb8724a --- /dev/null +++ b/basic/source/classes/image.cxx @@ -0,0 +1,544 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_basic.hxx" +#include <tools/stream.hxx> +#include <tools/tenccvt.hxx> +#include <basic/sbx.hxx> +#include "sb.hxx" +#include <string.h> // memset() etc +#include "image.hxx" +#include <codegen.hxx> +SbiImage::SbiImage() +{ + pStringOff = NULL; + pStrings = NULL; + pCode = NULL; + pLegacyPCode = NULL; + nFlags = 0; + nStrings = 0; + nStringSize= 0; + nCodeSize = 0; + nLegacyCodeSize = + nDimBase = 0; + bInit = + bError = FALSE; + bFirstInit = TRUE; + eCharSet = gsl_getSystemTextEncoding(); +} + +SbiImage::~SbiImage() +{ + Clear(); +} + +void SbiImage::Clear() +{ + delete[] pStringOff; + delete[] pStrings; + delete[] pCode; + ReleaseLegacyBuffer(); + pStringOff = NULL; + pStrings = NULL; + pCode = NULL; + nFlags = 0; + nStrings = 0; + nStringSize= 0; + nLegacyCodeSize = 0; + nCodeSize = 0; + eCharSet = gsl_getSystemTextEncoding(); + nDimBase = 0; + bError = FALSE; +} + +/************************************************************************** +* +* Service-Routines for Load/Store +* +**************************************************************************/ + +BOOL SbiGood( SvStream& r ) +{ + return BOOL( !r.IsEof() && r.GetError() == SVSTREAM_OK ); +} + +// Open Record +ULONG SbiOpenRecord( SvStream& r, UINT16 nSignature, UINT16 nElem ) +{ + ULONG nPos = r.Tell(); + r << nSignature << (INT32) 0 << nElem; + return nPos; +} + +// Close Record +void SbiCloseRecord( SvStream& r, ULONG nOff ) +{ + ULONG nPos = r.Tell(); + r.Seek( nOff + 2 ); + r << (INT32) ( nPos - nOff - 8 ); + r.Seek( nPos ); +} + +/************************************************************************** +* +* Load/Store +* +**************************************************************************/ + +// If the version number does not find, binary parts are omitted, but not +// source, comments and name +BOOL SbiImage::Load( SvStream& r ) +{ + UINT32 nVersion = 0; // Versionsnumber + return Load( r, nVersion ); +} +BOOL SbiImage::Load( SvStream& r, UINT32& nVersion ) +{ + + UINT16 nSign, nCount; + UINT32 nLen, nOff; + + Clear(); + // Read Master-Record + r >> nSign >> nLen >> nCount; + ULONG nLast = r.Tell() + nLen; + UINT32 nCharSet; // System charset + UINT32 lDimBase; + UINT16 nReserved1; + UINT32 nReserved2; + UINT32 nReserved3; + BOOL bBadVer = FALSE; + if( nSign == B_MODULE ) + { + r >> nVersion >> nCharSet >> lDimBase + >> nFlags >> nReserved1 >> nReserved2 >> nReserved3; + eCharSet = (CharSet) nCharSet; + eCharSet = GetSOLoadTextEncoding( eCharSet ); + bBadVer = BOOL( nVersion > B_CURVERSION ); + nDimBase = (USHORT) lDimBase; + } + + bool bLegacy = ( nVersion < B_EXT_IMG_VERSION ); + + ULONG nNext; + while( ( nNext = r.Tell() ) < nLast ) + { + short i; + + r >> nSign >> nLen >> nCount; + nNext += nLen + 8; + if( r.GetError() == SVSTREAM_OK ) + switch( nSign ) + { + case B_NAME: + r.ReadByteString( aName, eCharSet ); + //r >> aName; + break; + case B_COMMENT: + r.ReadByteString( aComment, eCharSet ); + //r >> aComment; + break; + case B_SOURCE: + { + String aTmp; + r.ReadByteString( aTmp, eCharSet ); + aOUSource = aTmp; + //r >> aSource; + break; + } +#ifdef EXTENDED_BINARY_MODULES + case B_EXTSOURCE: + { + for( UINT16 j = 0 ; j < nCount ; j++ ) + { + String aTmp; + r.ReadByteString( aTmp, eCharSet ); + aOUSource += aTmp; + } + break; + } +#endif + case B_PCODE: + if( bBadVer ) break; + pCode = new char[ nLen ]; + nCodeSize = nLen; + r.Read( pCode, nCodeSize ); + if ( bLegacy ) + { + ReleaseLegacyBuffer(); // release any previously held buffer + nLegacyCodeSize = (UINT16) nCodeSize; + pLegacyPCode = pCode; + + PCodeBuffConvertor< UINT16, UINT32 > aLegacyToNew( (BYTE*)pLegacyPCode, nLegacyCodeSize ); + aLegacyToNew.convert(); + pCode = (char*)aLegacyToNew.GetBuffer(); + nCodeSize = aLegacyToNew.GetSize(); + // we don't release the legacy buffer + // right now, thats because the module + // needs it to fix up the method + // nStart members. When that is done + // the module can release the buffer + // or it can wait until this routine + // is called again or when this class // destructs all of which will trigger + // release of the buffer. + } + break; + case B_PUBLICS: + case B_POOLDIR: + case B_SYMPOOL: + case B_LINERANGES: + break; + case B_STRINGPOOL: + if( bBadVer ) break; + MakeStrings( nCount ); + for( i = 0; i < nStrings && SbiGood( r ); i++ ) + { + r >> nOff; + pStringOff[ i ] = (USHORT) nOff; + } + r >> nLen; + if( SbiGood( r ) ) + { + delete [] pStrings; + pStrings = new sal_Unicode[ nLen ]; + nStringSize = (USHORT) nLen; + + char* pByteStrings = new char[ nLen ]; + r.Read( pByteStrings, nStringSize ); + for( short j = 0; j < nStrings; j++ ) + { + USHORT nOff2 = (USHORT) pStringOff[ j ]; + String aStr( pByteStrings + nOff2, eCharSet ); + memcpy( pStrings + nOff2, aStr.GetBuffer(), (aStr.Len() + 1) * sizeof( sal_Unicode ) ); + } + delete[] pByteStrings; + } break; + case B_MODEND: + goto done; + default: + break; + } + else + break; + r.Seek( nNext ); + } +done: + r.Seek( nLast ); + //if( eCharSet != ::GetSystemCharSet() ) + //ConvertStrings(); + if( !SbiGood( r ) ) + bError = TRUE; + return BOOL( !bError ); +} + +BOOL SbiImage::Save( SvStream& r, UINT32 nVer ) +{ + bool bLegacy = ( nVer < B_EXT_IMG_VERSION ); + + // detect if old code exceeds legacy limits + // if so, then disallow save + if ( bLegacy && ExceedsLegacyLimits() ) + { + SbiImage aEmptyImg; + aEmptyImg.aName = aName; + aEmptyImg.Save( r, B_LEGACYVERSION ); + return TRUE; + } + // First of all the header + ULONG nStart = SbiOpenRecord( r, B_MODULE, 1 ); + ULONG nPos; + + eCharSet = GetSOStoreTextEncoding( eCharSet ); + if ( bLegacy ) + r << (INT32) B_LEGACYVERSION; + else + r << (INT32) B_CURVERSION; + r << (INT32) eCharSet + << (INT32) nDimBase + << (INT16) nFlags + << (INT16) 0 + << (INT32) 0 + << (INT32) 0; + + // Name? + if( aName.Len() && SbiGood( r ) ) + { + nPos = SbiOpenRecord( r, B_NAME, 1 ); + r.WriteByteString( aName, eCharSet ); + //r << aName; + SbiCloseRecord( r, nPos ); + } + // Comment? + if( aComment.Len() && SbiGood( r ) ) + { + nPos = SbiOpenRecord( r, B_COMMENT, 1 ); + r.WriteByteString( aComment, eCharSet ); + //r << aComment; + SbiCloseRecord( r, nPos ); + } + // Source? + if( aOUSource.getLength() && SbiGood( r ) ) + { + nPos = SbiOpenRecord( r, B_SOURCE, 1 ); + String aTmp; + sal_Int32 nLen = aOUSource.getLength(); + const sal_Int32 nMaxUnitSize = STRING_MAXLEN - 1; + if( nLen > STRING_MAXLEN ) + aTmp = aOUSource.copy( 0, nMaxUnitSize ); + else + aTmp = aOUSource; + r.WriteByteString( aTmp, eCharSet ); + //r << aSource; + SbiCloseRecord( r, nPos ); + +#ifdef EXTENDED_BINARY_MODULES + if( nLen > STRING_MAXLEN ) + { + sal_Int32 nRemainingLen = nLen - nMaxUnitSize; + UINT16 nUnitCount = UINT16( (nRemainingLen + nMaxUnitSize - 1) / nMaxUnitSize ); + nPos = SbiOpenRecord( r, B_EXTSOURCE, nUnitCount ); + for( UINT16 i = 0 ; i < nUnitCount ; i++ ) + { + sal_Int32 nCopyLen = + (nRemainingLen > nMaxUnitSize) ? nMaxUnitSize : nRemainingLen; + String aTmp2 = aOUSource.copy( (i+1) * nMaxUnitSize, nCopyLen ); + nRemainingLen -= nCopyLen; + r.WriteByteString( aTmp2, eCharSet ); + } + SbiCloseRecord( r, nPos ); + } +#endif + } + // Binary data? + if( pCode && SbiGood( r ) ) + { + nPos = SbiOpenRecord( r, B_PCODE, 1 ); + if ( bLegacy ) + { + ReleaseLegacyBuffer(); // release any previously held buffer + PCodeBuffConvertor< UINT32, UINT16 > aNewToLegacy( (BYTE*)pCode, nCodeSize ); + aNewToLegacy.convert(); + pLegacyPCode = (char*)aNewToLegacy.GetBuffer(); + nLegacyCodeSize = aNewToLegacy.GetSize(); + r.Write( pLegacyPCode, nLegacyCodeSize ); + } + else + r.Write( pCode, nCodeSize ); + SbiCloseRecord( r, nPos ); + } + // String-Pool? + if( nStrings ) + { + nPos = SbiOpenRecord( r, B_STRINGPOOL, nStrings ); + // For every String: + // UINT32 Offset of the Strings in the Stringblock + short i; + + for( i = 0; i < nStrings && SbiGood( r ); i++ ) + r << (UINT32) pStringOff[ i ]; + + // Then the String-Block + char* pByteStrings = new char[ nStringSize ]; + for( i = 0; i < nStrings; i++ ) + { + USHORT nOff = (USHORT) pStringOff[ i ]; + ByteString aStr( pStrings + nOff, eCharSet ); + memcpy( pByteStrings + nOff, aStr.GetBuffer(), (aStr.Len() + 1) * sizeof( char ) ); + } + r << (UINT32) nStringSize; + r.Write( pByteStrings, nStringSize ); + + delete[] pByteStrings; + SbiCloseRecord( r, nPos ); + } + // Set overall length + SbiCloseRecord( r, nStart ); + if( !SbiGood( r ) ) + bError = TRUE; + return BOOL( !bError ); +} + +/************************************************************************** +* +* Routines called by the compiler +* +**************************************************************************/ + +void SbiImage::MakeStrings( short nSize ) +{ + nStrings = 0; + nStringIdx = 0; + nStringOff = 0; + nStringSize = 1024; + pStrings = new sal_Unicode[ nStringSize ]; + pStringOff = new UINT32[ nSize ]; + if( pStrings && pStringOff ) + { + nStrings = nSize; + memset( pStringOff, 0, nSize * sizeof( UINT32 ) ); + memset( pStrings, 0, nStringSize * sizeof( sal_Unicode ) ); + } + else + bError = TRUE; +} + +// Hinzufuegen eines Strings an den StringPool. Der String-Puffer +// waechst dynamisch in 1K-Schritten +// Add a string to StringPool. The String buffer is dynamically +// growing in 1K-Steps +void SbiImage::AddString( const String& r ) +{ + if( nStringIdx >= nStrings ) + bError = TRUE; + if( !bError ) + { + xub_StrLen len = r.Len() + 1; + UINT32 needed = nStringOff + len; + if( needed > 0xFFFFFF00L ) + bError = TRUE; // out of mem! + else if( needed > nStringSize ) + { + UINT32 nNewLen = needed + 1024; + nNewLen &= 0xFFFFFC00; // trim to 1K border + if( nNewLen > 0xFFFFFF00L ) + nNewLen = 0xFFFFFF00L; + sal_Unicode* p = NULL; + if( (p = new sal_Unicode[ nNewLen ]) != NULL ) + { + memcpy( p, pStrings, nStringSize * sizeof( sal_Unicode ) ); + delete[] pStrings; + pStrings = p; + nStringSize = sal::static_int_cast< UINT16 >(nNewLen); + } + else + bError = TRUE; + } + if( !bError ) + { + pStringOff[ nStringIdx++ ] = nStringOff; + //ByteString aByteStr( r, eCharSet ); + memcpy( pStrings + nStringOff, r.GetBuffer(), len * sizeof( sal_Unicode ) ); + nStringOff = nStringOff + len; + // Last String? The update the size of the buffer + if( nStringIdx >= nStrings ) + nStringSize = nStringOff; + } + } +} + +// Add code block +// The block was fetched by the compiler from class SbBuffer and +// is already created with new. Additionally it contains all Integers +// in Big Endian format, so can be directly read/written. +void SbiImage::AddCode( char* p, UINT32 s ) +{ + pCode = p; + nCodeSize = s; +} + +// Add user type +void SbiImage::AddType(SbxObject* pObject) +{ + if( !rTypes.Is() ) + rTypes = new SbxArray; + SbxObject *pCopyObject = new SbxObject(*pObject); + rTypes->Insert (pCopyObject,rTypes->Count()); +} + +void SbiImage::AddEnum(SbxObject* pObject) // Register enum type +{ + if( !rEnums.Is() ) + rEnums = new SbxArray; + rEnums->Insert( pObject, rEnums->Count() ); +} + + +/************************************************************************** +* +* Accessing the image +* +**************************************************************************/ + +// Note: IDs start with 1 +String SbiImage::GetString( short nId ) const +{ + if( nId && nId <= nStrings ) + { + UINT32 nOff = pStringOff[ nId - 1 ]; + sal_Unicode* pStr = pStrings + nOff; + + // #i42467: Special treatment for vbNullChar + if( *pStr == 0 ) + { + UINT32 nNextOff = (nId < nStrings) ? pStringOff[ nId ] : nStringOff; + UINT32 nLen = nNextOff - nOff - 1; + if( nLen == 1 ) + { + // Force length 1 and make char 0 afterwards + String aNullCharStr( String::CreateFromAscii( " " ) ); + aNullCharStr.SetChar( 0, 0 ); + return aNullCharStr; + } + } + else + { + String aStr( pStr ); + return aStr; + } + } + return String(); +} + +const SbxObject* SbiImage::FindType (String aTypeName) const +{ + return rTypes.Is() ? (SbxObject*)rTypes->Find(aTypeName,SbxCLASS_OBJECT) : NULL; +} + +UINT16 SbiImage::CalcLegacyOffset( INT32 nOffset ) +{ + return SbiCodeGen::calcLegacyOffSet( (BYTE*)pCode, nOffset ) ; +} + +UINT32 SbiImage::CalcNewOffset( INT16 nOffset ) +{ + return SbiCodeGen::calcNewOffSet( (BYTE*)pLegacyPCode, nOffset ) ; +} + +void SbiImage::ReleaseLegacyBuffer() +{ + delete[] pLegacyPCode; + pLegacyPCode = NULL; + nLegacyCodeSize = 0; +} + +BOOL SbiImage::ExceedsLegacyLimits() +{ + if ( ( nStringSize > 0xFF00L ) || ( CalcLegacyOffset( nCodeSize ) > 0xFF00L ) ) + return TRUE; + return FALSE; +} |