Files
libreoffice/basic/source/classes/image.cxx

459 lines
13 KiB
C++
Raw Normal View History

2000-09-18 15:18:56 +00:00
/*************************************************************************
*
* $RCSfile: image.cxx,v $
*
* $Revision: 1.11 $
2000-09-18 15:18:56 +00:00
*
* last change: $Author: rt $ $Date: 2004-11-15 16:34:02 $
2000-09-18 15:18:56 +00:00
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library 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 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (the "License"); You may not use this file
* except in compliance with the License. You may obtain a copy of the
* License at http://www.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2000 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
#ifndef _STREAM_HXX //autogen
#include <tools/stream.hxx>
#endif
#include <tools/tenccvt.hxx>
2000-09-18 15:18:56 +00:00
#pragma hdrstop
#include <svtools/sbx.hxx>
#include "sb.hxx"
#include <string.h> // memset() etc
#include "image.hxx"
#include "filefmt.hxx"
SbiImage::SbiImage()
{
pStringOff = NULL;
pStrings = NULL;
pCode = NULL;
nFlags =
nStrings =
nStringSize=
nCodeSize =
nDimBase = 0;
bInit =
bError = FALSE;
2001-09-04 09:14:43 +00:00
bFirstInit = TRUE;
2000-09-18 15:18:56 +00:00
eCharSet = gsl_getSystemTextEncoding();
}
SbiImage::~SbiImage()
{
Clear();
}
void SbiImage::Clear()
{
delete[] pStringOff;
delete[] pStrings;
delete[] pCode;
2000-09-18 15:18:56 +00:00
pStringOff = NULL;
pStrings = NULL;
pCode = NULL;
nFlags =
nStrings =
nStringSize=
nCodeSize = 0;
eCharSet = gsl_getSystemTextEncoding();
nDimBase = 0;
bError = FALSE;
}
/**************************************************************************
*
* Service-Routinen fuer das Laden und Speichern
*
**************************************************************************/
BOOL SbiGood( SvStream& r )
{
return BOOL( !r.IsEof() && r.GetError() == SVSTREAM_OK );
}
// Oeffnen eines Records
ULONG SbiOpenRecord( SvStream& r, UINT16 nSignature, UINT16 nElem )
{
ULONG nPos = r.Tell();
r << nSignature << (INT32) 0 << nElem;
return nPos;
}
// Schliessen eines Records
void SbiCloseRecord( SvStream& r, ULONG nOff )
{
ULONG nPos = r.Tell();
r.Seek( nOff + 2 );
r << (INT32) ( nPos - nOff - 8 );
r.Seek( nPos );
}
/**************************************************************************
*
* Laden und Speichern
*
**************************************************************************/
// Falls die Versionsnummer nicht passt, werden die binaeren Teile
// nicht geladen, wohl aber Source, Kommentar und Name.
BOOL SbiImage::Load( SvStream& r )
{
UINT16 nSign, nCount;
UINT32 nLen, nOff;
Clear();
ULONG nStart = r.Tell();
// Master-Record einlesen
r >> nSign >> nLen >> nCount;
ULONG nLast = r.Tell() + nLen;
UINT32 nVersion = 0; // Versionsnummer
UINT32 nCharSet; // System-Zeichensatz
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 );
2000-09-18 15:18:56 +00:00
bBadVer = BOOL( nVersion != B_CURVERSION );
nDimBase = (USHORT) lDimBase;
}
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;
2000-09-18 15:18:56 +00:00
//r >> aSource;
break;
}
2000-09-18 15:18:56 +00:00
case B_PCODE:
if( bBadVer ) break;
pCode = new char[ nLen ];
nCodeSize = (USHORT) nLen;
r.Read( pCode, nCodeSize );
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;
2000-09-18 15:18:56 +00:00
pStrings = new sal_Unicode[ nLen ];
nStringSize = (USHORT) nLen;
char* pByteStrings = new char[ nLen ];
r.Read( pByteStrings, nStringSize );
for( short i = 0; i < nStrings; i++ )
{
USHORT nOff = pStringOff[ i ];
String aStr( pByteStrings + nOff, eCharSet );
memcpy( pStrings + nOff, aStr.GetBuffer(), (aStr.Len() + 1) * sizeof( sal_Unicode ) );
}
delete[] pByteStrings;
2000-09-18 15:18:56 +00:00
} 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 )
{
// Erst mal der Header:
ULONG nStart = SbiOpenRecord( r, B_MODULE, 1 );
ULONG nPos;
eCharSet = GetSOStoreTextEncoding( eCharSet );
2000-09-18 15:18:56 +00:00
r << (INT32) B_CURVERSION
<< (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 );
}
// Kommentar?
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 ) )
2000-09-18 15:18:56 +00:00
{
nPos = SbiOpenRecord( r, B_SOURCE, 1 );
String aTmp;
sal_Int32 nLen = aOUSource.getLength();
if( nLen > STRING_MAXLEN )
aTmp = aOUSource.copy( 0, STRING_MAXLEN - 1 );
else
aTmp = aOUSource;
r.WriteByteString( aTmp, eCharSet );
2000-09-18 15:18:56 +00:00
//r << aSource;
SbiCloseRecord( r, nPos );
}
// Binaere Daten?
if( pCode && SbiGood( r ) )
{
nPos = SbiOpenRecord( r, B_PCODE, 1 );
r.Write( pCode, nCodeSize );
SbiCloseRecord( r, nPos );
}
// String-Pool?
if( nStrings )
{
nPos = SbiOpenRecord( r, B_STRINGPOOL, nStrings );
// Fuer jeden String:
// UINT32 Offset des Strings im Stringblock
short i;
for( i = 0; i < nStrings && SbiGood( r ); i++ )
2000-09-18 15:18:56 +00:00
r << (UINT32) pStringOff[ i ];
// Danach der String-Block
char* pByteStrings = new char[ nStringSize ];
for( i = 0; i < nStrings; i++ )
{
USHORT nOff = 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;
2000-09-18 15:18:56 +00:00
SbiCloseRecord( r, nPos );
}
// Und die Gesamtlaenge setzen
SbiCloseRecord( r, nStart );
if( !SbiGood( r ) )
bError = TRUE;
return BOOL( !bError );
}
/**************************************************************************
*
* Routinen, die auch vom Compiler gerufen werden
*
**************************************************************************/
void SbiImage::MakeStrings( short nSize )
{
nStrings = nStringIdx = nStringOff = 0;
nStringSize = 1024;
pStrings = new sal_Unicode[ nStringSize ];
pStringOff = new UINT16[ nSize ];
if( pStrings && pStringOff )
{
nStrings = nSize;
memset( pStringOff, 0, nSize * sizeof( UINT16 ) );
memset( pStrings, 0, nStringSize * sizeof( sal_Unicode ) );
}
else
bError = TRUE;
}
// Hinzufuegen eines Strings an den StringPool. Der String-Puffer
// waechst dynamisch in 1K-Schritten
2001-11-13 11:00:49 +00:00
2000-09-18 15:18:56 +00:00
void SbiImage::AddString( const String& r )
{
if( nStringIdx >= nStrings )
bError = TRUE;
if( !bError )
{
UINT16 len = r.Len() + 1;
long needed = (long) nStringOff + len;
if( needed > 0xFF00L )
bError = TRUE; // out of mem!
else if( (USHORT) needed > nStringSize )
{
2001-11-13 11:00:49 +00:00
UINT16 nNewLen = needed + 1024;
nNewLen &= 0xFC00; // trim to 1K border
sal_Unicode* p = new sal_Unicode[ nNewLen ];
2000-09-18 15:18:56 +00:00
if( p )
{
memcpy( p, pStrings, nStringSize * sizeof( sal_Unicode ) );
delete[] pStrings;
2000-09-18 15:18:56 +00:00
pStrings = p;
2001-11-13 12:45:56 +00:00
nStringSize = nNewLen;
2000-09-18 15:18:56 +00:00
}
else
bError = TRUE;
}
if( !bError )
{
pStringOff[ nStringIdx++ ] = nStringOff;
//ByteString aByteStr( r, eCharSet );
memcpy( pStrings + nStringOff, r.GetBuffer(), len * sizeof( sal_Unicode ) );
nStringOff += len;
// war das der letzte String? Dann die Groesse
// des Puffers aktualisieren
if( nStringIdx >= nStrings )
nStringSize = nStringOff;
}
}
}
// Codeblock hinzufuegen
// Der Block wurde vom Compiler aus der Klasse SbBuffer herausgeholt
// und ist bereits per new angelegt. Ausserdem enthaelt er alle Integers
// im Big Endian-Format, kann also direkt gelesen/geschrieben werden.
void SbiImage::AddCode( char* p, USHORT s )
{
pCode = p;
nCodeSize = s;
}
void SbiImage::AddType(SbxObject* pObject) // User-Type mit aufnehmen
{
if( !rTypes.Is() )
rTypes = new SbxArray;
2000-09-18 15:18:56 +00:00
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() );
}
2000-09-18 15:18:56 +00:00
/**************************************************************************
*
* Zugriffe auf das Image
*
**************************************************************************/
// IDs zaehlen ab 1!!
String SbiImage::GetString( short nId ) const
{
if( nId && nId <= nStrings )
{
USHORT nOff = pStringOff[ --nId ];
String aStr( pStrings + nOff );
return aStr;
}
return String();
}
const SbxObject* SbiImage::FindType (String aTypeName) const
{
return rTypes.Is() ? (SbxObject*)rTypes->Find(aTypeName,SbxCLASS_OBJECT) : NULL;
2000-09-18 15:18:56 +00:00
}