/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"

#define ENABLE_BYTESTRING_STREAM_OPERATORS

#include <tools/urlobj.hxx>
#include <tools/vcompat.hxx>
#include <unotools/streamwrap.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <unotools/tempfile.hxx>
#include <unotools/localfilehelper.hxx>
#include <ucbhelper/content.hxx>
#include <sot/storage.hxx>
#include <sot/formats.hxx>
#include <sot/filelist.hxx>
#include <vcl/virdev.hxx>
#include <vcl/cvtgrf.hxx>
#include <svl/itempool.hxx>
#include <sfx2/docfile.hxx>
#include <avmedia/mediawindow.hxx>
#include <svx/svdograf.hxx>
#include <svx/fmpage.hxx>
#include "codec.hxx"
#include <svx/unomodel.hxx>
#include <svx/fmmodel.hxx>
#include <svx/fmview.hxx>
#include "svx/galmisc.hxx"
#include "svx/galtheme.hxx"
#include <com/sun/star/sdbc/XResultSet.hpp>
#include <com/sun/star/ucb/XContentAccess.hpp>
#include <com/sun/star/io/XInputStream.hpp>
#include "galobj.hxx"
#include <svx/gallery1.hxx>
#include "galtheme.hrc"
#include <vcl/lstbox.hxx>
#include "gallerydrawmodel.hxx"

// --------------
// - Namespaces -
// --------------

using namespace ::rtl;
using namespace ::com::sun::star;

// ------------
// - SgaTheme -
// ------------
DBG_NAME(GalleryTheme)

GalleryTheme::GalleryTheme( Gallery* pGallery, GalleryThemeEntry* pThemeEntry ) :
		pParent               ( pGallery ),
		pThm		          ( pThemeEntry ),
        mnThemeLockCount      ( 0 ),      
		mnBroadcasterLockCount( 0 ),
		nDragPos	          ( 0 ),
		bDragging	          ( sal_False )
{
    DBG_CTOR(GalleryTheme,NULL);

	ImplCreateSvDrawStorage();

	if( pThm->IsImported() )
		aImportName = pThm->GetThemeName();
}

// ------------------------------------------------------------------------

GalleryTheme::~GalleryTheme()
{
	ImplWrite();

	for( GalleryObject* pEntry = aObjectList.First(); pEntry; pEntry = aObjectList.Next() )
	{
		Broadcast( GalleryHint( GALLERY_HINT_CLOSE_OBJECT, GetName(), reinterpret_cast< sal_uIntPtr >( pEntry ) ) );
		delete pEntry;
		Broadcast( GalleryHint( GALLERY_HINT_OBJECT_REMOVED, GetName(), reinterpret_cast< sal_uIntPtr >( pEntry ) ) );
	}

    DBG_DTOR(GalleryTheme,NULL);
}

// ------------------------------------------------------------------------

void GalleryTheme::ImplCreateSvDrawStorage()
{
	if( !pThm->IsImported() )
	{
		aSvDrawStorageRef = new SvStorage( sal_False, GetSdvURL().GetMainURL( INetURLObject::NO_DECODE ), pThm->IsReadOnly() ? STREAM_READ : STREAM_STD_READWRITE );
		// #i50423# ReadOnly may not been set though the file can't be written (because of security reasons)
		if ( ( aSvDrawStorageRef->GetError() != ERRCODE_NONE ) && !pThm->IsReadOnly() )	
			aSvDrawStorageRef = new SvStorage( sal_False, GetSdvURL().GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ );
	}
	else
		aSvDrawStorageRef.Clear();
}

// ------------------------------------------------------------------------

sal_Bool GalleryTheme::ImplWriteSgaObject( const SgaObject& rObj, sal_uIntPtr nPos, GalleryObject* pExistentEntry )
{
	SvStream*	pOStm = ::utl::UcbStreamHelper::CreateStream( GetSdgURL().GetMainURL( INetURLObject::NO_DECODE ), STREAM_WRITE );
	sal_Bool		bRet = sal_False;

	if( pOStm )
	{
		const sal_uInt32 nOffset = pOStm->Seek( STREAM_SEEK_TO_END );

		rObj.WriteData( *pOStm, m_aDestDir );

		if( !pOStm->GetError() )
		{
			GalleryObject* pEntry;

			if( !pExistentEntry )
			{
				pEntry = new GalleryObject;
				aObjectList.Insert( pEntry, nPos );
			}
			else
				pEntry = pExistentEntry;

			pEntry->aURL = rObj.GetURL();
			pEntry->nOffset = nOffset;
			pEntry->eObjKind = rObj.GetObjKind();
			bRet = sal_True;
		}

		delete pOStm;
	}

	return bRet;
}

// ------------------------------------------------------------------------

SgaObject* GalleryTheme::ImplReadSgaObject( GalleryObject* pEntry )
{
	SgaObject* pSgaObj = NULL;

	if( pEntry )
	{
		SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( GetSdgURL().GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ );

		if( pIStm )
		{
			sal_uInt32 nInventor;

			// Ueberpruefen, ob das File ein gueltiges SGA-File ist
			pIStm->Seek( pEntry->nOffset );
			*pIStm >> nInventor;

			if( nInventor == COMPAT_FORMAT( 'S', 'G', 'A', '3' ) )
			{
				pIStm->Seek( pEntry->nOffset );

				switch( pEntry->eObjKind )
				{
					case( SGA_OBJ_BMP ):	pSgaObj = new SgaObjectBmp(); break;
					case( SGA_OBJ_ANIM ):	pSgaObj = new SgaObjectAnim(); break;
					case( SGA_OBJ_INET ):	pSgaObj = new SgaObjectINet(); break;
					case( SGA_OBJ_SVDRAW ):	pSgaObj = new SgaObjectSvDraw(); break;
					case( SGA_OBJ_SOUND ):	pSgaObj = new SgaObjectSound(); break;

					default:
					break;
				}

				if( pSgaObj )
				{
					*pIStm >> *pSgaObj;
					pSgaObj->ImplUpdateURL( pEntry->aURL );
				}
			}

			delete pIStm;
		}
	}

	return pSgaObj;
}

// ------------------------------------------------------------------------

void GalleryTheme::ImplRead()
{
	SvStream* pIStm	= ::utl::UcbStreamHelper::CreateStream( GetThmURL().GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ );

	if( pIStm )
	{
		*pIStm >> *this;
		delete pIStm;
	}
}

// ------------------------------------------------------------------------

void GalleryTheme::ImplWrite()
{
	if( IsModified() )
	{
		INetURLObject aPathURL( GetThmURL() );

		aPathURL.removeSegment();
		aPathURL.removeFinalSlash();

		DBG_ASSERT( aPathURL.GetProtocol() != INET_PROT_NOT_VALID, "invalid URL" );

		if( FileExists( aPathURL ) || CreateDir( aPathURL ) )
		{
#ifdef UNX
			SvStream* pOStm	= ::utl::UcbStreamHelper::CreateStream( GetThmURL().GetMainURL( INetURLObject::NO_DECODE ), STREAM_WRITE | STREAM_COPY_ON_SYMLINK | STREAM_TRUNC );
#else
			SvStream* pOStm	= ::utl::UcbStreamHelper::CreateStream( GetThmURL().GetMainURL( INetURLObject::NO_DECODE ), STREAM_WRITE | STREAM_TRUNC );
#endif

			if( pOStm )
			{
				*pOStm << *this;
				delete pOStm;
			}

			ImplSetModified( sal_False );
		}
	}
}

// ------------------------------------------------------------------------

const GalleryObject* GalleryTheme::ImplGetGalleryObject( const INetURLObject& rURL )
{
	GalleryObject*	pEntry = aObjectList.First();
	GalleryObject*	pFoundEntry = NULL;

	for( ; pEntry && !pFoundEntry; pEntry = aObjectList.Next() )
		if( pEntry->aURL == rURL )
			pFoundEntry = pEntry;

	return pFoundEntry;
}

// ------------------------------------------------------------------------

INetURLObject GalleryTheme::ImplGetURL( const GalleryObject* pObject ) const
{
	INetURLObject aURL;

	if( pObject )
	{
		if( IsImported() )
		{
			INetURLObject aPathURL( GetParent()->GetImportURL( GetName() ) );

			aPathURL.removeSegment();
			aPathURL.removeFinalSlash();
			aPathURL.Append( pObject->aURL.GetName() );
			aURL = aPathURL;
		}
		else
			aURL = pObject->aURL;
	}

	return aURL;
}

// ------------------------------------------------------------------------

INetURLObject GalleryTheme::ImplCreateUniqueURL( SgaObjKind eObjKind, sal_uIntPtr nFormat )
{
    INetURLObject   aDir( GetParent()->GetUserURL() );
    INetURLObject   aInfoFileURL( GetParent()->GetUserURL() );
    INetURLObject   aNewURL;
	sal_uInt32		nNextNumber = 1999;
    sal_Char const* pExt = NULL;
    sal_Bool            bExists;

    aDir.Append( String( RTL_CONSTASCII_USTRINGPARAM( "dragdrop" ) ) );
    CreateDir( aDir );

	aInfoFileURL.Append( String( RTL_CONSTASCII_USTRINGPARAM( "sdddndx1" ) ) );

	// read next possible number
    if( FileExists( aInfoFileURL ) )
	{
		SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aInfoFileURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ );

		if( pIStm )
		{
			*pIStm >> nNextNumber;
			delete pIStm;
		}
	}

    // create extension
    if( nFormat )
    {
        switch( nFormat )
        {
            case( CVT_BMP ): pExt = ".bmp"; break;
            case( CVT_GIF ): pExt = ".gif"; break;
            case( CVT_JPG ): pExt = ".jpg"; break;
            case( CVT_MET ): pExt = ".met"; break;
            case( CVT_PCT ): pExt = ".pct"; break;
            case( CVT_PNG ): pExt = ".png"; break;
            case( CVT_SVM ): pExt = ".svm"; break;
            case( CVT_TIF ): pExt = ".tif"; break;
            case( CVT_WMF ): pExt = ".wmf"; break;
            case( CVT_EMF ): pExt = ".emf"; break;

            default:
                pExt = ".grf";
            break;
        }
    }

    do
    {
        // get URL
	    if( SGA_OBJ_SVDRAW == eObjKind )
	    {
            String aFileName( RTL_CONSTASCII_USTRINGPARAM( "gallery/svdraw/dd" ) );
		    aNewURL = INetURLObject( aFileName += String::CreateFromInt32( ++nNextNumber % 99999999 ), INET_PROT_PRIV_SOFFICE );

            bExists = sal_False;

		    for( GalleryObject* pEntry = aObjectList.First(); pEntry && !bExists; pEntry = aObjectList.Next() )
			    if( pEntry->aURL == aNewURL )
                    bExists = sal_True;
	    }
	    else
	    {
            String aFileName( RTL_CONSTASCII_USTRINGPARAM( "dd" ) );

            aFileName += String::CreateFromInt32( ++nNextNumber % 999999 );
            aFileName += String( pExt, RTL_TEXTENCODING_ASCII_US );

            aNewURL = aDir;
		    aNewURL.Append( aFileName );

            bExists = FileExists( aNewURL );
	    }
    }
    while( bExists );

	// write updated number
    SvStream* pOStm = ::utl::UcbStreamHelper::CreateStream( aInfoFileURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_WRITE );

	if( pOStm )
	{
		*pOStm << nNextNumber;
		delete pOStm;
	}

	return aNewURL;
}

// ------------------------------------------------------------------------

void GalleryTheme::ImplBroadcast( sal_uIntPtr nUpdatePos )
{
	if( !IsBroadcasterLocked() )
	{
		if( GetObjectCount() && ( nUpdatePos >= GetObjectCount() ) )
			nUpdatePos = GetObjectCount() - 1;

		Broadcast( GalleryHint( GALLERY_HINT_THEME_UPDATEVIEW, GetName(), nUpdatePos ) );
	}
}

// ------------------------------------------------------------------------

sal_Bool GalleryTheme::UnlockTheme()
{
    DBG_ASSERT( mnThemeLockCount, "Theme is not locked" );
    
    sal_Bool bRet = sal_False;
    
    if( mnThemeLockCount )
    {
        --mnThemeLockCount;
        bRet = sal_True;
    }
    
    return bRet;
}

// ------------------------------------------------------------------------

void GalleryTheme::UnlockBroadcaster( sal_uIntPtr nUpdatePos )
{
	DBG_ASSERT( mnBroadcasterLockCount, "Broadcaster is not locked" );

	if( mnBroadcasterLockCount && !--mnBroadcasterLockCount )
		ImplBroadcast( nUpdatePos );
}

// ------------------------------------------------------------------------

sal_Bool GalleryTheme::InsertObject( const SgaObject& rObj, sal_uIntPtr nInsertPos )
{
	sal_Bool bRet = sal_False;

	if( rObj.IsValid() )
	{
		GalleryObject*	pEntry = aObjectList.First();
		GalleryObject*	pFoundEntry = NULL;

		for( ; pEntry && !pFoundEntry; pEntry = aObjectList.Next() )
			if( pEntry->aURL == rObj.GetURL() )
				pFoundEntry = pEntry;

		if( pFoundEntry )
        {
    		GalleryObject aNewEntry;

            // update title of new object if neccessary
            if( !rObj.GetTitle().Len() )
            {
                SgaObject* pOldObj = ImplReadSgaObject( pFoundEntry );

                if( pOldObj )
                {
                    ( (SgaObject&) rObj ).SetTitle( pOldObj->GetTitle() );
                    delete pOldObj;
                }
            }
            else if( rObj.GetTitle() == String( RTL_CONSTASCII_USTRINGPARAM( "__<empty>__" ) ) )
                ( (SgaObject&) rObj ).SetTitle( String() );

            ImplWriteSgaObject( rObj, nInsertPos, &aNewEntry );
			pFoundEntry->nOffset = aNewEntry.nOffset;
        }
		else
			ImplWriteSgaObject( rObj, nInsertPos, NULL );

		ImplSetModified( bRet = sal_True );
		ImplBroadcast( pFoundEntry ? aObjectList.GetPos( pFoundEntry ) : nInsertPos );
	}

	return bRet;
}

// ------------------------------------------------------------------------

SgaObject* GalleryTheme::AcquireObject( sal_uIntPtr nPos )
{
	return ImplReadSgaObject( aObjectList.GetObject( nPos ) );
}

// ------------------------------------------------------------------------

void GalleryTheme::GetPreviewBitmapExAndStrings(sal_uIntPtr nPos, BitmapEx& rBitmapEx, Size& rSize, String& rTitle, String& rPath) const
{
    const GalleryObject* pGalleryObject = aObjectList.GetObject(nPos);

    if(pGalleryObject)
    {
        rBitmapEx = pGalleryObject->maPreviewBitmapEx;
        rSize = pGalleryObject->maPreparedSize;
        rTitle = pGalleryObject->maTitle;
        rPath = pGalleryObject->maPath;
    }
    else
    {
        OSL_ENSURE(false, "OOps, no GalleryObject at this index (!)");
    }
}

// ------------------------------------------------------------------------

void GalleryTheme::SetPreviewBitmapExAndStrings(sal_uIntPtr nPos, const BitmapEx& rBitmapEx, const Size& rSize, const String& rTitle, const String& rPath)
{
    GalleryObject* pGalleryObject = aObjectList.GetObject(nPos);

    if(pGalleryObject)
    {
        pGalleryObject->maPreviewBitmapEx = rBitmapEx;
        pGalleryObject->maPreparedSize = rSize;
        pGalleryObject->maTitle = rTitle;
        pGalleryObject->maPath = rPath;
    }
    else
    {
        OSL_ENSURE(false, "OOps, no GalleryObject at this index (!)");
    }
}

// ------------------------------------------------------------------------

void GalleryTheme::ReleaseObject( SgaObject* pObject )
{
	delete pObject;
}

// ------------------------------------------------------------------------

sal_Bool GalleryTheme::RemoveObject( sal_uIntPtr nPos )
{
	GalleryObject* pEntry = aObjectList.Remove( nPos );

	if( !aObjectList.Count() )
		KillFile( GetSdgURL() );

	if( pEntry )
	{
		if( SGA_OBJ_SVDRAW == pEntry->eObjKind )
			aSvDrawStorageRef->Remove( pEntry->aURL.GetMainURL( INetURLObject::NO_DECODE ) );

		Broadcast( GalleryHint( GALLERY_HINT_CLOSE_OBJECT, GetName(), reinterpret_cast< sal_uIntPtr >( pEntry ) ) );
		delete pEntry;
		Broadcast( GalleryHint( GALLERY_HINT_OBJECT_REMOVED, GetName(), reinterpret_cast< sal_uIntPtr >( pEntry ) ) );

		ImplSetModified( sal_True );
		ImplBroadcast( nPos );
	}

	return( pEntry != NULL );
}

// ------------------------------------------------------------------------

sal_Bool GalleryTheme::ChangeObjectPos( sal_uIntPtr nOldPos, sal_uIntPtr nNewPos )
{
	sal_Bool bRet = sal_False;

	if( nOldPos != nNewPos )
	{
		GalleryObject* pEntry = aObjectList.GetObject( nOldPos );

		if( pEntry )
		{
			aObjectList.Insert( pEntry, nNewPos );

			if( nNewPos < nOldPos )
				nOldPos++;

			aObjectList.Remove( nOldPos );
			ImplSetModified( bRet = sal_True );
			ImplBroadcast( ( nNewPos < nOldPos ) ? nNewPos : ( nNewPos - 1 ) );
		}
	}

	return bRet;
}

// ------------------------------------------------------------------------

void GalleryTheme::Actualize( const Link& rActualizeLink, GalleryProgress* pProgress )
{
	if( !IsReadOnly() && !IsImported() )
	{
		Graphic			aGraphic;
		String			aFormat;
		GalleryObject*	pEntry;
		const sal_uIntPtr		nCount = aObjectList.Count();
		sal_uIntPtr			i;

		LockBroadcaster();
		bAbortActualize = sal_False;

		// LoeschFlag zuruecksetzen
		for ( i = 0; i < nCount; i++ )
			aObjectList.GetObject( i )->mbDelete = false;

		for( i = 0; ( i < nCount ) && !bAbortActualize; i++ )
		{
			if( pProgress )
				pProgress->Update( i, nCount - 1 );

			pEntry = aObjectList.GetObject( i );

            const INetURLObject aURL( pEntry->aURL );

            rActualizeLink.Call( (void*) &aURL );

			// SvDraw-Objekte werden spaeter aktualisiert
			if( pEntry->eObjKind != SGA_OBJ_SVDRAW )
			{
				// Hier muss noch etwas eingebaut werden,
				// das Files auf den ensprechenden Eintrag matched
				// Grafiken als Grafik-Objekte in die Gallery aufnehmen
				if( pEntry->eObjKind == SGA_OBJ_SOUND )
				{
					SgaObjectSound aObjSound( aURL );
					if( !InsertObject( aObjSound ) )
						pEntry->mbDelete = true;
				}
				else
				{
					aGraphic.Clear();

					if ( GalleryGraphicImport( aURL, aGraphic, aFormat ) )
					{
						SgaObject* pNewObj;

						if ( SGA_OBJ_INET == pEntry->eObjKind )
							pNewObj = (SgaObject*) new SgaObjectINet( aGraphic, aURL, aFormat );
						else if ( aGraphic.IsAnimated() )
							pNewObj = (SgaObject*) new SgaObjectAnim( aGraphic, aURL, aFormat );
						else
							pNewObj = (SgaObject*) new SgaObjectBmp( aGraphic, aURL, aFormat );

						if( !InsertObject( *pNewObj ) )
							pEntry->mbDelete = true;

						delete pNewObj;
					}
					else
						pEntry->mbDelete = true; // Loesch-Flag setzen
				}
			}
			else
			{
				if ( aSvDrawStorageRef.Is() )
				{
					const String		aStmName( GetSvDrawStreamNameFromURL( pEntry->aURL ) );
					SvStorageStreamRef	pIStm = aSvDrawStorageRef->OpenSotStream( aStmName, STREAM_READ );

					if( pIStm && !pIStm->GetError() )
					{
						pIStm->SetBufferSize( 16384 );

						SgaObjectSvDraw aNewObj( *pIStm, pEntry->aURL );

                        if( !InsertObject( aNewObj ) )
							pEntry->mbDelete = true;

						pIStm->SetBufferSize( 0L );
					}
				}
			}
		}

		// remove all entries with set flag
		pEntry = aObjectList.First();
		while( pEntry )
		{
			if( pEntry->mbDelete )
			{
				Broadcast( GalleryHint( GALLERY_HINT_CLOSE_OBJECT, GetName(), reinterpret_cast< sal_uIntPtr >( pEntry ) ) );
				delete aObjectList.Remove( pEntry );
				Broadcast( GalleryHint( GALLERY_HINT_OBJECT_REMOVED, GetName(), reinterpret_cast< sal_uIntPtr >( pEntry ) ) );

				pEntry = aObjectList.GetCurObject();
			}
			else
				pEntry = aObjectList.Next();
		}

		// update theme
		::utl::TempFile	aTmp;
		INetURLObject	aInURL( GetSdgURL() );
		INetURLObject	aTmpURL( aTmp.GetURL() );

		DBG_ASSERT( aInURL.GetProtocol() != INET_PROT_NOT_VALID, "invalid URL" );
		DBG_ASSERT( aTmpURL.GetProtocol() != INET_PROT_NOT_VALID, "invalid URL" );

		SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( aInURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ );
		SvStream* pTmpStm = ::utl::UcbStreamHelper::CreateStream( aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_WRITE | STREAM_TRUNC );

		if( pIStm && pTmpStm )
		{
			pEntry = aObjectList.First();

			while( pEntry )
			{
				SgaObject* pObj;

				switch( pEntry->eObjKind )
				{
					case( SGA_OBJ_BMP ):	pObj = new SgaObjectBmp(); break;
					case( SGA_OBJ_ANIM ):	pObj = new SgaObjectAnim(); break;
					case( SGA_OBJ_INET ):	pObj = new SgaObjectINet(); break;
					case( SGA_OBJ_SVDRAW ):	pObj = new SgaObjectSvDraw(); break;
					case (SGA_OBJ_SOUND):	pObj = new SgaObjectSound(); break;

					default:
						pObj = NULL;
					break;
				}

				if( pObj )
				{
					pIStm->Seek( pEntry->nOffset );
					*pIStm >> *pObj;
					pEntry->nOffset = pTmpStm->Tell();
					*pTmpStm << *pObj;
					delete pObj;
				}

				pEntry = aObjectList.Next();
			}
		}
		else
		{
			DBG_ERROR( "File(s) could not be opened" );
		}

		delete pIStm;
		delete pTmpStm;

		CopyFile( aTmpURL, aInURL );
		KillFile( aTmpURL );

		sal_uIntPtr nStorErr = 0;

		{
			SvStorageRef aTempStorageRef( new SvStorage( sal_False, aTmpURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_STD_READWRITE ) );
			aSvDrawStorageRef->CopyTo( aTempStorageRef );
			nStorErr = aSvDrawStorageRef->GetError();
		}

		if( !nStorErr )
		{
			aSvDrawStorageRef.Clear();
			CopyFile( aTmpURL, GetSdvURL() );
			ImplCreateSvDrawStorage();
		}

		KillFile( aTmpURL );
		ImplSetModified( sal_True );
		ImplWrite();
		UnlockBroadcaster();
	}
}

// ------------------------------------------------------------------------

GalleryThemeEntry* GalleryTheme::CreateThemeEntry( const INetURLObject& rURL, sal_Bool bReadOnly )
{
	DBG_ASSERT( rURL.GetProtocol() != INET_PROT_NOT_VALID, "invalid URL" );

	GalleryThemeEntry*	pRet = NULL;

	if( FileExists( rURL ) )
	{
		SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( rURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ );

		if( pIStm )
		{
			String			aThemeName;
			sal_uInt32		nThemeId = 0;
			sal_uInt16		nVersion;
			sal_Bool			bThemeNameFromResource = sal_False;

			*pIStm >> nVersion;

			if( nVersion <= 0x00ff )
			{
				ByteString aTmpStr;

				*pIStm >> aTmpStr; aThemeName = String( aTmpStr.GetBuffer(), RTL_TEXTENCODING_UTF8 );

				// Charakterkonvertierung durchfuehren
				if( nVersion >= 0x0004 )
				{
					sal_uInt32	nCount;
					sal_uInt16	nTemp16;

					*pIStm >> nCount >> nTemp16;
					pIStm->Seek( STREAM_SEEK_TO_END );

					// pruefen, ob es sich um eine neuere Version handelt;
					// daher um 520Bytes (8Bytes Kennung + 512Bytes Reserverpuffer ) zurueckspringen,
					// falls dies ueberhaupt moeglich ist
					if( pIStm->Tell() >= 520 )
					{
						sal_uInt32 nId1, nId2;

						pIStm->SeekRel( -520 );
						*pIStm >> nId1 >> nId2;

						if( nId1 == COMPAT_FORMAT( 'G', 'A', 'L', 'R' ) &&
							nId2 == COMPAT_FORMAT( 'E', 'S', 'R', 'V' ) )
						{
							VersionCompat* pCompat = new VersionCompat( *pIStm, STREAM_READ );

							*pIStm >> nThemeId;

							if( pCompat->GetVersion() >= 2 )
							{
								*pIStm >> bThemeNameFromResource;
							}

							delete pCompat;
						}
					}
				}

				INetURLObject aPathURL( rURL );

				aPathURL.removeSegment();
				aPathURL.removeFinalSlash();
				pRet = new GalleryThemeEntry( aPathURL, aThemeName,
											  String(rURL.GetBase()).Copy( 2, 6 ).ToInt32(),
											  bReadOnly, sal_False, sal_False, nThemeId,
											  bThemeNameFromResource );
			}

			delete pIStm;
		}
	}

	return pRet;
}

// -----------------------------------------------------------------------------

sal_Bool GalleryTheme::GetThumb( sal_uIntPtr nPos, BitmapEx& rBmp, sal_Bool )
{
	SgaObject*	pObj = AcquireObject( nPos );
	sal_Bool		bRet = sal_False;

	if( pObj )
	{
		rBmp = pObj->GetThumbBmp();
		ReleaseObject( pObj );
		bRet = sal_True;
	}

	return bRet;
}

// -----------------------------------------------------------------------------

sal_Bool GalleryTheme::GetGraphic( sal_uIntPtr nPos, Graphic& rGraphic, sal_Bool bProgress )
{
	const GalleryObject*	pObject = ImplGetGalleryObject( nPos );
	sal_Bool					bRet = sal_False;

	if( pObject )
	{
		const INetURLObject aURL( ImplGetURL( pObject ) );

		switch( pObject->eObjKind )
		{
			case( SGA_OBJ_BMP ):
			case( SGA_OBJ_ANIM ):
			case( SGA_OBJ_INET ):
			{
				String aFilterDummy;
				bRet = ( GalleryGraphicImport( aURL, rGraphic, aFilterDummy, bProgress ) != SGA_IMPORT_NONE );
			}
			break;

			case( SGA_OBJ_SVDRAW ):
			{
                SvxGalleryDrawModel aModel;

                if( aModel.GetModel() )
                {
				    if( GetModel( nPos, *aModel.GetModel(), bProgress ) )
				    {
					    ImageMap aIMap;

					    if( CreateIMapGraphic( *aModel.GetModel(), rGraphic, aIMap ) )
						    bRet = sal_True;
					    else
					    {
						    VirtualDevice aVDev;
						    aVDev.SetMapMode( MapMode( MAP_100TH_MM ) );
						    FmFormView aView( aModel.GetModel(), &aVDev );

						    aView.hideMarkHandles();
						    aView.ShowSdrPage(aView.GetModel()->GetPage(0));
						    aView.MarkAll();
						    rGraphic = aView.GetAllMarkedGraphic();
						    bRet = sal_True;
					    }
				    }
                }
			}
			break;

			case( SGA_OBJ_SOUND ):
			{
				SgaObject* pObj = AcquireObject( nPos );

				if( pObj )
				{
                    rGraphic = pObj->GetThumbBmp();
					//Bitmap aBmp( pObj->GetThumbBmp() );
					//aBmp.Replace( COL_LIGHTMAGENTA, COL_WHITE );
					//rGraphic = aBmp;
					ReleaseObject( pObj );
					bRet = sal_True;
				}
			}
			break;

			default:
			break;
		}
	}

	return bRet;
}

// -----------------------------------------------------------------------------

sal_Bool GalleryTheme::InsertGraphic( const Graphic& rGraphic, sal_uIntPtr nInsertPos )
{
	sal_Bool bRet = sal_False;

	if( rGraphic.GetType() != GRAPHIC_NONE )
    {
		sal_uIntPtr           nExportFormat = CVT_UNKNOWN;
		const GfxLink	aGfxLink( ( (Graphic&) rGraphic ).GetLink() );

		if( aGfxLink.GetDataSize() )
		{
			switch( aGfxLink.GetType() )
			{
				case( GFX_LINK_TYPE_EPS_BUFFER ): nExportFormat = CVT_SVM; break;
				case( GFX_LINK_TYPE_NATIVE_GIF ): nExportFormat = CVT_GIF; break;
				case( GFX_LINK_TYPE_NATIVE_JPG ): nExportFormat = CVT_JPG; break;
				case( GFX_LINK_TYPE_NATIVE_PNG ): nExportFormat = CVT_PNG; break;
				case( GFX_LINK_TYPE_NATIVE_TIF ): nExportFormat = CVT_TIF; break;
				case( GFX_LINK_TYPE_NATIVE_WMF ): nExportFormat = CVT_WMF; break;
				case( GFX_LINK_TYPE_NATIVE_MET ): nExportFormat = CVT_MET; break;
				case( GFX_LINK_TYPE_NATIVE_PCT ): nExportFormat = CVT_PCT; break;
				case( GFX_LINK_TYPE_NATIVE_SVG ): nExportFormat = CVT_SVG; break;
				default:
					break;
			}
		}
		else
		{
		    if( rGraphic.GetType() == GRAPHIC_BITMAP )
		    {
			    if( rGraphic.IsAnimated() )
				    nExportFormat = CVT_GIF;
			    else
				    nExportFormat = CVT_PNG;
		    }
		    else
                nExportFormat = CVT_SVM;
		}

        const INetURLObject aURL( ImplCreateUniqueURL( SGA_OBJ_BMP, nExportFormat ) );
		SvStream*           pOStm = ::utl::UcbStreamHelper::CreateStream( aURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_WRITE | STREAM_TRUNC );

        if( pOStm )
        {
		    pOStm->SetVersion( SOFFICE_FILEFORMAT_50 );

            if( CVT_SVM == nExportFormat )
            {
                GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() );
                
			    aMtf.Write( *pOStm );
			    bRet = ( pOStm->GetError() == ERRCODE_NONE );
            }
            else
            {
                if( aGfxLink.GetDataSize() && aGfxLink.GetData() )
                {
                    pOStm->Write( aGfxLink.GetData(), aGfxLink.GetDataSize() );
                    bRet = ( pOStm->GetError() == ERRCODE_NONE );
                }
                else
                    bRet = ( GraphicConverter::Export( *pOStm, rGraphic, nExportFormat ) == ERRCODE_NONE );
            }

            delete pOStm;
        }

		if( bRet )
		{
			const SgaObjectBmp aObjBmp( aURL.GetMainURL( INetURLObject::NO_DECODE ) );
			InsertObject( aObjBmp, nInsertPos );
		}
	}

	return bRet;
}

// -----------------------------------------------------------------------------

sal_Bool GalleryTheme::GetModel( sal_uIntPtr nPos, SdrModel& rModel, sal_Bool )
{
	const GalleryObject*	pObject = ImplGetGalleryObject( nPos );
	sal_Bool					bRet = sal_False;

	if( pObject && ( SGA_OBJ_SVDRAW == pObject->eObjKind ) )
	{
		const INetURLObject aURL( ImplGetURL( pObject ) );
		SvStorageRef		xStor( GetSvDrawStorage() );

		if( xStor.Is() )
		{
			const String		aStmName( GetSvDrawStreamNameFromURL( aURL ) );
			SvStorageStreamRef	xIStm( xStor->OpenSotStream( aStmName, STREAM_READ ) );

			if( xIStm.Is() && !xIStm->GetError() )
			{
				xIStm->SetBufferSize( STREAMBUF_SIZE );
				bRet = GallerySvDrawImport( *xIStm, rModel );
				xIStm->SetBufferSize( 0L );
			}
		}
	}

	return bRet;
}

// -----------------------------------------------------------------------------

sal_Bool GalleryTheme::InsertModel( const FmFormModel& rModel, sal_uIntPtr nInsertPos )
{
	INetURLObject	aURL( ImplCreateUniqueURL( SGA_OBJ_SVDRAW ) );
	SvStorageRef	xStor( GetSvDrawStorage() );
	sal_Bool			bRet = sal_False;

	if( xStor.Is() )
	{
		const String		aStmName( GetSvDrawStreamNameFromURL( aURL ) );
		SvStorageStreamRef	xOStm( xStor->OpenSotStream( aStmName, STREAM_WRITE | STREAM_TRUNC ) );

		if( xOStm.Is() && !xOStm->GetError() )
		{
			SvMemoryStream	aMemStm( 65535, 65535 );
			FmFormModel*	pFormModel = (FmFormModel*) &rModel;

		    pFormModel->BurnInStyleSheetAttributes();
		    
            {
			    uno::Reference< io::XOutputStream > xDocOut( new utl::OOutputStreamWrapper( aMemStm ) );

        	    if( xDocOut.is() )
                    SvxDrawingLayerExport( pFormModel, xDocOut );
		    }

            aMemStm.Seek( 0 );

		    xOStm->SetBufferSize( 16348 );
			GalleryCodec aCodec( *xOStm );
		    aCodec.Write( aMemStm );

		    if( !xOStm->GetError() )
		    {
			    SgaObjectSvDraw	aObjSvDraw( rModel, aURL );
			    bRet = InsertObject( aObjSvDraw, nInsertPos );
		    }

		    xOStm->SetBufferSize( 0L );
            xOStm->Commit();
        }
	}

	return bRet;
}

// -----------------------------------------------------------------------------

sal_Bool GalleryTheme::GetModelStream( sal_uIntPtr nPos, SotStorageStreamRef& rxModelStream, sal_Bool )
{
	const GalleryObject*	pObject = ImplGetGalleryObject( nPos );
	sal_Bool					bRet = sal_False;

	if( pObject && ( SGA_OBJ_SVDRAW == pObject->eObjKind ) )
	{
		const INetURLObject aURL( ImplGetURL( pObject ) );
		SvStorageRef		xStor( GetSvDrawStorage() );

		if( xStor.Is() )
		{
			const String		aStmName( GetSvDrawStreamNameFromURL( aURL ) );
			SvStorageStreamRef	xIStm( xStor->OpenSotStream( aStmName, STREAM_READ ) );

			if( xIStm.Is() && !xIStm->GetError() )
			{
            	sal_uInt32 nVersion = 0;

                xIStm->SetBufferSize( 16348 );

	            if( GalleryCodec::IsCoded( *xIStm, nVersion ) )
                {
                    SvxGalleryDrawModel aModel;

                    if( aModel.GetModel() )
                    {
                        if( GallerySvDrawImport( *xIStm, *aModel.GetModel() ) )
                        {
                            aModel.GetModel()->BurnInStyleSheetAttributes();

                            {
                                uno::Reference< io::XOutputStream > xDocOut( new utl::OOutputStreamWrapper( *rxModelStream ) );

                                if( SvxDrawingLayerExport( aModel.GetModel(), xDocOut ) )
                                    rxModelStream->Commit();
                            }
                        }

                        bRet = ( rxModelStream->GetError() == ERRCODE_NONE );
                    }
                }

                xIStm->SetBufferSize( 0 );
			}
		}
	}

	return bRet;
}

// -----------------------------------------------------------------------------

sal_Bool GalleryTheme::InsertModelStream( const SotStorageStreamRef& rxModelStream, sal_uIntPtr nInsertPos )
{
	INetURLObject	aURL( ImplCreateUniqueURL( SGA_OBJ_SVDRAW ) );
	SvStorageRef	xStor( GetSvDrawStorage() );
	sal_Bool			bRet = sal_False;

	if( xStor.Is() )
	{
		const String		aStmName( GetSvDrawStreamNameFromURL( aURL ) );
		SvStorageStreamRef	xOStm( xStor->OpenSotStream( aStmName, STREAM_WRITE | STREAM_TRUNC ) );

		if( xOStm.Is() && !xOStm->GetError() )
		{
            GalleryCodec    aCodec( *xOStm );
            SvMemoryStream  aMemStm( 65535, 65535 );

		    xOStm->SetBufferSize( 16348 );
            aCodec.Write( *rxModelStream );

		    if( !xOStm->GetError() )
		    {
			    xOStm->Seek( 0 );
                SgaObjectSvDraw	aObjSvDraw( *xOStm, aURL );
			    bRet = InsertObject( aObjSvDraw, nInsertPos );
		    }

		    xOStm->SetBufferSize( 0L );
            xOStm->Commit();
        }
	}

	return bRet;
}

// -----------------------------------------------------------------------------

sal_Bool GalleryTheme::GetURL( sal_uIntPtr nPos, INetURLObject& rURL, sal_Bool )
{
	const GalleryObject*	pObject = ImplGetGalleryObject( nPos );
	sal_Bool					bRet = sal_False;

	if( pObject )
	{
		rURL = INetURLObject( ImplGetURL( pObject ) );
		bRet = sal_True;
	}

	return bRet;
}

// -----------------------------------------------------------------------------

sal_Bool GalleryTheme::InsertURL( const INetURLObject& rURL, sal_uIntPtr nInsertPos )
{
	Graphic			aGraphic;
	String			aFormat;
	SgaObject*		pNewObj = NULL;
	const sal_uInt16	nImportRet = GalleryGraphicImport( rURL, aGraphic, aFormat );
	sal_Bool			bRet = sal_False;

	if( nImportRet != SGA_IMPORT_NONE )
	{
		if ( SGA_IMPORT_INET == nImportRet )
			pNewObj = (SgaObject*) new SgaObjectINet( aGraphic, rURL, aFormat );
		else if ( aGraphic.IsAnimated() )
			pNewObj = (SgaObject*) new SgaObjectAnim( aGraphic, rURL, aFormat );
		else
			pNewObj = (SgaObject*) new SgaObjectBmp( aGraphic, rURL, aFormat );
	}
	else if( ::avmedia::MediaWindow::isMediaURL( rURL.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS ) ) )
		pNewObj = (SgaObject*) new SgaObjectSound( rURL );

	if( pNewObj && InsertObject( *pNewObj, nInsertPos ) )
		bRet = sal_True;

	delete pNewObj;

	return bRet;
}

// -----------------------------------------------------------------------------

sal_Bool GalleryTheme::InsertFileOrDirURL( const INetURLObject& rFileOrDirURL, sal_uIntPtr nInsertPos )
{
    INetURLObject                   aURL;
    ::std::vector< INetURLObject >  aURLVector;
	sal_Bool                            bRet = sal_False;

	try
	{
		::ucbhelper::Content         aCnt( rFileOrDirURL.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ucb::XCommandEnvironment >() );
		sal_Bool        bFolder = false;

		aCnt.getPropertyValue( OUString::createFromAscii( "IsFolder" ) ) >>= bFolder;

		if( bFolder )
		{
			uno::Sequence< OUString > aProps( 1 );
			aProps.getArray()[ 0 ] = OUString::createFromAscii( "Url" );
			uno::Reference< sdbc::XResultSet > xResultSet( aCnt.createCursor( aProps, ::ucbhelper::INCLUDE_DOCUMENTS_ONLY ) );
            uno::Reference< ucb::XContentAccess > xContentAccess( xResultSet, uno::UNO_QUERY );
			if( xContentAccess.is() )
			{
				while( xResultSet->next() )
				{
					aURL.SetSmartURL( xContentAccess->queryContentIdentifierString() );
                    aURLVector.push_back( aURL );
				}
			}
		}
		else
            aURLVector.push_back( rFileOrDirURL );
	}
	catch( const ucb::ContentCreationException& )
	{
	}
	catch( const uno::RuntimeException& )
	{
	}
	catch( const uno::Exception& )
	{
	}

    ::std::vector< INetURLObject >::const_iterator aIter( aURLVector.begin() ), aEnd( aURLVector.end() );

    while( aIter != aEnd )
        bRet = bRet || InsertURL( *aIter++, nInsertPos );

    return bRet;
}

// -----------------------------------------------------------------------------

sal_Bool GalleryTheme::InsertTransferable( const uno::Reference< datatransfer::XTransferable >& rxTransferable, sal_uIntPtr nInsertPos )
{
	sal_Bool bRet = sal_False;

	if( rxTransferable.is() )
	{
		TransferableDataHelper	aDataHelper( rxTransferable );
		Graphic*				pGraphic = NULL;

		if( aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ) )
		{
			SotStorageStreamRef xModelStm;

			if( aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_DRAWING, xModelStm ) )
				bRet = InsertModelStream( xModelStm, nInsertPos );
		}
		else if( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) ||
                 aDataHelper.HasFormat( FORMAT_FILE ) )
		{
            FileList aFileList;

            if( aDataHelper.HasFormat( SOT_FORMAT_FILE_LIST ) )
                aDataHelper.GetFileList( SOT_FORMAT_FILE_LIST, aFileList );
            else
            {
                String aFile;

                aDataHelper.GetString( FORMAT_FILE, aFile );

                if( aFile.Len() )
                    aFileList.AppendFile( aFile );
            }

            for( sal_uInt32 i = 0, nCount = aFileList.Count(); i < nCount; ++i )
            {
                const String    aFile( aFileList.GetFile( i ) );
                INetURLObject   aURL( aFile );

                if( aURL.GetProtocol() == INET_PROT_NOT_VALID )
                {
                    String aLocalURL;

                    if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aFile, aLocalURL ) )
                        aURL = INetURLObject( aLocalURL );
                }

                if( aURL.GetProtocol() != INET_PROT_NOT_VALID )
                    bRet = InsertFileOrDirURL( aURL, nInsertPos );
			}
		}
		else
		{
			Graphic	aGraphic;
			sal_uIntPtr	nFormat = 0;

			if( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) )
				nFormat = SOT_FORMATSTR_ID_SVXB;
			else if( aDataHelper.HasFormat( FORMAT_GDIMETAFILE ) )
				nFormat = FORMAT_GDIMETAFILE;
			else if( aDataHelper.HasFormat( FORMAT_BITMAP ) )
				nFormat = FORMAT_BITMAP;

			if( nFormat && aDataHelper.GetGraphic( nFormat, aGraphic ) )
				pGraphic = new Graphic( aGraphic );
		}

		if( pGraphic )
		{
			bRet = sal_False;

			if( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVIM ) )
			{

				ImageMap aImageMap;

                // according to KA we don't need a BaseURL here
                if( aDataHelper.GetImageMap( SOT_FORMATSTR_ID_SVIM, aImageMap ) )
				{
                    SvxGalleryDrawModel aModel;

                    if( aModel.GetModel() )
                    {
					    SgaUserDataFactory	aFactory;

					    SdrPage*	pPage = aModel.GetModel()->GetPage(0);
					    SdrGrafObj*	pGrafObj = new SdrGrafObj( *pGraphic );

					    pGrafObj->InsertUserData( new SgaIMapInfo( aImageMap ) );
					    pPage->InsertObject( pGrafObj );
					    bRet = InsertModel( *aModel.GetModel(), nInsertPos );
                    }
				}
			}

			if( !bRet )
				bRet = InsertGraphic( *pGraphic, nInsertPos );

			delete pGraphic;
		}
	}

	return bRet;
}

// -----------------------------------------------------------------------------

void GalleryTheme::CopyToClipboard( Window* pWindow, sal_uIntPtr nPos )
{
	GalleryTransferable* pTransferable = new GalleryTransferable( this, nPos, false );
	pTransferable->CopyToClipboard( pWindow );
}

// -----------------------------------------------------------------------------

void GalleryTheme::StartDrag( Window* pWindow, sal_uIntPtr nPos )
{
	GalleryTransferable* pTransferable = new GalleryTransferable( this, nPos, true );
	pTransferable->StartDrag( pWindow, DND_ACTION_COPY | DND_ACTION_LINK );
}

// -----------------------------------------------------------------------------

SvStream& GalleryTheme::WriteData( SvStream& rOStm ) const
{
	const INetURLObject	aRelURL1( GetParent()->GetRelativeURL() );
	const INetURLObject	aRelURL2( GetParent()->GetUserURL() );
	INetURLObject		aNewURL, aTempURL;
	sal_uInt32			nCount = GetObjectCount();
	sal_Bool				bRel;

	rOStm << (sal_uInt16) 0x0004;
	rOStm << ByteString( GetRealName(), RTL_TEXTENCODING_UTF8 );
	rOStm << nCount << (sal_uInt16) gsl_getSystemTextEncoding();

	for( sal_uInt32 i = 0; i < nCount; i++ )
	{
		const GalleryObject* pObj = ImplGetGalleryObject( i );
		String				 aPath;

		if( SGA_OBJ_SVDRAW == pObj->eObjKind )
		{
			aPath = GetSvDrawStreamNameFromURL( pObj->aURL );
			bRel = sal_False;
		}
		else
		{
			aPath = pObj->aURL.GetMainURL( INetURLObject::NO_DECODE );
			bRel = ( ( aPath.Erase( sal::static_int_cast< xub_StrLen >( aRelURL1.GetMainURL( INetURLObject::NO_DECODE ).getLength() ) ) ) == String(aRelURL1.GetMainURL( INetURLObject::NO_DECODE ) ));

			if( bRel && ( pObj->aURL.GetMainURL( INetURLObject::NO_DECODE ).getLength() > ( aRelURL1.GetMainURL( INetURLObject::NO_DECODE ).getLength() + 1 ) ) )
			{
				aPath = pObj->aURL.GetMainURL( INetURLObject::NO_DECODE );
				aPath = aPath.Erase( 0, sal::static_int_cast< xub_StrLen >( aRelURL1.GetMainURL( INetURLObject::NO_DECODE ).getLength() ) );
			}
			else
			{
				aPath = pObj->aURL.GetMainURL( INetURLObject::NO_DECODE );
				bRel = ( ( aPath.Erase( sal::static_int_cast< xub_StrLen >( aRelURL2.GetMainURL( INetURLObject::NO_DECODE ).getLength() ) ) ) == String(aRelURL2.GetMainURL( INetURLObject::NO_DECODE ) ));

				if( bRel && ( pObj->aURL.GetMainURL( INetURLObject::NO_DECODE ).getLength() > ( aRelURL2.GetMainURL( INetURLObject::NO_DECODE ).getLength() + 1 ) ) )
				{
					aPath = pObj->aURL.GetMainURL( INetURLObject::NO_DECODE );
					aPath = aPath.Erase( 0, sal::static_int_cast< xub_StrLen >( aRelURL2.GetMainURL( INetURLObject::NO_DECODE ).getLength() ) );
				}
				else
					aPath = pObj->aURL.GetMainURL( INetURLObject::NO_DECODE );
			}
		}

		aPath.SearchAndReplace(m_aDestDir, String());
		rOStm << bRel << ByteString( aPath, RTL_TEXTENCODING_UTF8 ) << pObj->nOffset << (sal_uInt16) pObj->eObjKind;
	}

	// neuerdings wird ein 512-Byte-Reservepuffer gechrieben;
	// um diesen zu erkennen werden zwei sal_uIntPtr-Ids geschrieben
	rOStm << COMPAT_FORMAT( 'G', 'A', 'L', 'R' ) << COMPAT_FORMAT( 'E', 'S', 'R', 'V' );

	const long		nReservePos = rOStm.Tell();
	VersionCompat*	pCompat = new VersionCompat( rOStm, STREAM_WRITE, 2 );

	rOStm << (sal_uInt32) GetId() << IsThemeNameFromResource(); // ab Version 2

	delete pCompat;

	// Rest des Puffers auffuellen
	const long	nRest = Max( 512L - ( (long) rOStm.Tell() - nReservePos ), 0L );

	if( nRest )
	{
		char* pReserve = new char[ nRest ];
		memset( pReserve, 0, nRest );
		rOStm.Write( pReserve, nRest );
		delete[] pReserve;
	}

	return rOStm;
}

// ------------------------------------------------------------------------

SvStream& GalleryTheme::ReadData( SvStream& rIStm )
{
	sal_uInt32			nCount;
	sal_uInt16			nVersion;
	ByteString			aTmpStr;
	String				aThemeName;
	rtl_TextEncoding	nTextEncoding;

	aImportName = String();
	rIStm >> nVersion >> aTmpStr >> nCount;

	if( nVersion >= 0x0004 )
	{
		sal_uInt16 nTmp16;
		rIStm >> nTmp16;
		nTextEncoding = (rtl_TextEncoding) nTmp16;
	}
	else
		nTextEncoding = RTL_TEXTENCODING_UTF8;

	aThemeName = String( aTmpStr.GetBuffer(), nTextEncoding );

	if( nCount <= ( 1L << 14 ) )
	{
		GalleryObject*	pObj;
		INetURLObject	aRelURL1( GetParent()->GetRelativeURL() );
		INetURLObject	aRelURL2( GetParent()->GetUserURL() );
		sal_uInt32		nId1, nId2;
		sal_Bool			bRel;

		for( pObj = aObjectList.First(); pObj; pObj = aObjectList.Next() )
		{
			Broadcast( GalleryHint( GALLERY_HINT_CLOSE_OBJECT, GetName(), reinterpret_cast< sal_uIntPtr >( pObj ) ) );
			delete pObj;
			Broadcast( GalleryHint( GALLERY_HINT_OBJECT_REMOVED, GetName(), reinterpret_cast< sal_uIntPtr >( pObj ) ) );
		}

		aObjectList.Clear();

		for( sal_uInt32 i = 0; i < nCount; i++ )
		{
			pObj = new GalleryObject;

			ByteString	aTempFileName;
			String		aFileName;
			String		aPath;
			sal_uInt16	nTemp;

			rIStm >> bRel >> aTempFileName >> pObj->nOffset;
			rIStm >> nTemp; pObj->eObjKind = (SgaObjKind) nTemp;

			aFileName = String( aTempFileName.GetBuffer(), gsl_getSystemTextEncoding() );

			if( bRel )
			{
				aFileName.SearchAndReplaceAll( '\\', '/' );
				aPath = aRelURL1.GetMainURL( INetURLObject::NO_DECODE );

				if( aFileName.GetChar( 0 ) != '/' )
			    		aPath += '/';

				aPath += aFileName;

				pObj->aURL = INetURLObject( aPath );

				if( !FileExists( pObj->aURL ) )
				{
					aPath = aRelURL2.GetMainURL( INetURLObject::NO_DECODE );

					if( aFileName.GetChar( 0 ) != '/' )
						aPath += '/';

					aPath += aFileName;

					// assign this URL, even in the case it is not valid (#94482)
                    pObj->aURL = INetURLObject( aPath );
				}
			}
			else
			{
				if( SGA_OBJ_SVDRAW == pObj->eObjKind )
				{
					const static String aBaseURLStr( RTL_CONSTASCII_USTRINGPARAM( "gallery/svdraw/" ) );

					String aDummyURL( aBaseURLStr );
					pObj->aURL = INetURLObject( aDummyURL += aFileName, INET_PROT_PRIV_SOFFICE );
				}
				else
				{
                    String aLocalURL;

					pObj->aURL = INetURLObject( aFileName );

					if( ( pObj->aURL.GetProtocol() == INET_PROT_NOT_VALID ) &&
						::utl::LocalFileHelper::ConvertPhysicalNameToURL( aFileName, aLocalURL ) )
					{
						pObj->aURL = INetURLObject( aLocalURL );
					}
				}
			}

			aObjectList.Insert( pObj, LIST_APPEND );
		}

		rIStm >> nId1 >> nId2;

		// in neueren Versionen befindet sich am Ende ein 512-Byte-Reservepuffer;
		// die Daten befinden sich am Anfang dieses Puffers und
		// sind durch eine VersionCompat geklammert
		if( !rIStm.IsEof() &&
			nId1 == COMPAT_FORMAT( 'G', 'A', 'L', 'R' ) &&
			nId2 == COMPAT_FORMAT( 'E', 'S', 'R', 'V' ) )
		{
			VersionCompat*	pCompat = new VersionCompat( rIStm, STREAM_READ );
			sal_uInt32		nTemp32;
			sal_Bool			bThemeNameFromResource = sal_False;

			rIStm >> nTemp32;

			if( pCompat->GetVersion() >= 2 )
			{
				rIStm >> bThemeNameFromResource;
			}

			SetId( nTemp32, bThemeNameFromResource );
			delete pCompat;
		}
	}
	else
		rIStm.SetError( SVSTREAM_READ_ERROR );

	ImplSetModified( sal_False );

	return rIStm;
}

// ------------------------------------------------------------------------

SvStream& operator<<( SvStream& rOut, const GalleryTheme& rTheme )
{
	return rTheme.WriteData( rOut );
}

// ------------------------------------------------------------------------

SvStream& operator>>( SvStream& rIn, GalleryTheme& rTheme )
{
	return rTheme.ReadData( rIn );
}

void GalleryTheme::ImplSetModified( sal_Bool bModified ) 
{ pThm->SetModified( bModified ); }

const String& GalleryTheme::GetRealName() const { return pThm->GetThemeName(); }
const INetURLObject& GalleryTheme::GetThmURL() const { return pThm->GetThmURL(); }
const INetURLObject& GalleryTheme::GetSdgURL() const { return pThm->GetSdgURL(); }
const INetURLObject& GalleryTheme::GetSdvURL() const { return pThm->GetSdvURL(); }
sal_uInt32 GalleryTheme::GetId() const { return pThm->GetId(); }
void GalleryTheme::SetId( sal_uInt32 nNewId, sal_Bool bResetThemeName ) { pThm->SetId( nNewId, bResetThemeName ); }
sal_Bool GalleryTheme::IsThemeNameFromResource() const { return pThm->IsNameFromResource(); }
sal_Bool GalleryTheme::IsImported() const { return pThm->IsImported(); }
sal_Bool GalleryTheme::IsReadOnly() const { return pThm->IsReadOnly(); }
sal_Bool GalleryTheme::IsDefault() const { return pThm->IsDefault(); }
sal_Bool GalleryTheme::IsModified() const { return pThm->IsModified(); }
const String& GalleryTheme::GetName() const	{ return IsImported() ? aImportName : pThm->GetThemeName(); }

void GalleryTheme::InsertAllThemes( ListBox& rListBox )
{
	for( sal_uInt16 i = RID_GALLERYSTR_THEME_FIRST; i <= RID_GALLERYSTR_THEME_LAST; i++ )
		rListBox.InsertEntry( String( GAL_RESID( i ) ) );
}

