/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * 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.
 *
 ************************************************************************/

#include <comphelper/classids.hxx>
#include <bf_svx/svxids.hrc>
#include <bf_svx/impgrf.hxx>

#include <bf_sfx2/app.hxx>
#include <bf_sfx2/fcontnr.hxx>
#include <bf_sfx2/docfile.hxx>
#include <bf_svtools/sfxecode.hxx>
#include <bf_svtools/FilterConfigItem.hxx>
#include <sot/formats.hxx>

#include <com/sun/star/util/XArchiver.hpp>

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


#ifdef _MSC_VER
#pragma hdrstop
#endif

#include "sddll.hxx"

#include "sddll0.hxx"         // wird durchs Makefile generiert

#include "bf_sd/grdocsh.hxx"
#include "strings.hrc"
#include "strmname.h"


#include <bf_offmgr/ofaids.hrc>

#include <bf_svtools/moduleoptions.hxx>

#include <legacysmgr/legacy_binfilters_smgr.hxx>
namespace binfilter {

TYPEINIT1( SdModuleDummy, SfxModule );

extern "C" { static void SAL_CALL thisModule() {} }

SFX_IMPL_MODULE_LIB(Sd, UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( DLL_NAME ) ) )

SFX_IMPL_OBJECTFACTORY_MOD(SdDrawDocShell, SFXOBJECTSHELL_STD_NORMAL, simpress,
                           SvGlobalName(BF_SO3_SIMPRESS_CLASSID), Sd, UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( DLL_NAME ) ) )
{
    SdDrawDocShell::Factory().SetDocumentServiceName( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.PresentationDocument" ) ) );
    SdDrawDocShell::Factory().GetFilterContainer()->SetDetectFilter( &SdDLL::DetectFilter );
}

SFX_IMPL_OBJECTFACTORY_MOD(SdGraphicDocShell, SFXOBJECTSHELL_STD_NORMAL, sdraw,
                           SvGlobalName(BF_SO3_SDRAW_CLASSID), Sd, UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( DLL_NAME ) ) )
{
    SdGraphicDocShell::Factory().SetDocumentServiceName( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.DrawingDocument" ) ) );
    SdGraphicDocShell::Factory().GetFilterContainer()->SetDetectFilter( &SdDLL::DetectFilter );
}

SdDLL::SdDLL()
{
}

SdDLL::~SdDLL()
{
}

void SdDLL::LibInit()
{
    /*SfxApplication* pApp =*/ SFX_APP();

    SfxObjectFactory *p1 = NULL;
    if(SvtModuleOptions().IsImpress())
    {
        SdDrawDocShell::RegisterFactory(SDT_SD_DOCFACTPRIO);
        p1 = &SdDrawDocShell::Factory();
    }

    SfxObjectFactory *p2 = NULL;
    if(SvtModuleOptions().IsDraw())
    {
        SdGraphicDocShell::RegisterFactory(SDT_SD_DOCFACTPRIO);
        p2 = &SdGraphicDocShell::Factory();
    }

    SD_MOD() = new SdModuleDummy( NULL, TRUE, p1, p2 );
}

void SdDLL::LibExit()
{
    FreeLibSd();
    DELETEZ( SD_MOD() );
}

ULONG SdDLL::DetectFilter(SfxMedium& rMedium, const SfxFilter** pFilter, SfxFilterFlags nMust, SfxFilterFlags nDont)
{
    ULONG nReturn = ERRCODE_ABORT;  // Erkennung fehlgeschlagen, Filter ungueltig
    BOOL bStorage = FALSE;

    if( *pFilter && (*pFilter)->GetFilterFlags() & SFX_FILTER_PACKED )
    {
        uno::Reference< lang::XMultiServiceFactory > xSMgr( ::legacy_binfilters::getLegacyProcessServiceFactory() );
        uno::Reference< util::XArchiver > xPacker( xSMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.Archiver" )) ), uno::UNO_QUERY );
        if( xPacker.is() )
        {
            // extract extra data
            OUString aPath( rMedium.GetOrigURL() );
            OUString aExtraData( xPacker->getExtraData( aPath ) );
            const OUString aSig1( RTL_CONSTASCII_USTRINGPARAM( "private:" ));
            String aTmp;
            aTmp += sal_Unicode( '?' );
            aTmp += (*pFilter)->GetFilterContainer()->GetName();
            const OUString aSig2( aTmp );
            INT32 nIndex1 = aExtraData.indexOf( aSig1 );
            INT32 nIndex2 = aExtraData.indexOf( aSig2 );
            if( nIndex1 == 0 && nIndex2 != -1 )
                return ERRCODE_NONE;
        }
    }
    else if (rMedium.GetError() == SVSTREAM_OK)
    {
        if (rMedium.IsStorage())
        {
            bStorage = TRUE;
            // Storage
            SvStorage* pStorage = rMedium.GetStorage();
            if ( pStorage == NULL ) return ULONG_MAX;


            // Erkennung ueber contained streams (StarDraw 3.0)
            if( ( pStorage->IsContained( pStarDrawDoc ) && pStorage->IsStream( pStarDrawDoc ) ) ||
                ( pStorage->IsContained( pStarDrawDoc3 ) && pStorage->IsStream( pStarDrawDoc3 ) ) )
            {
                const SfxFilter* pFilt = NULL;
                SfxFilterMatcher& rMatcher = SFX_APP()->GetFilterMatcher();
                SfxFilterContainer *pDraw = rMatcher.GetContainer(
                                            UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "sdraw" ) ) ); // Name kennt ihr besser
                SfxFilterContainer *pImpr = rMatcher.GetContainer(
                                            UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "simpress" ) )); // dito
                ULONG nStorFmt = pStorage->GetFormat();
                if (*pFilter)
                {
                    if ( (*pFilter)->GetFilterContainer() == pDraw)
                    {
                        if(SvtModuleOptions().IsDraw())
                        {
                            pFilt = pDraw->GetFilter4ClipBoardId( nStorFmt );
                            nReturn = ERRCODE_SFX_FORCEQUIET;
                        }
                        else
                        {
                            pFilt = pImpr->GetFilter4ClipBoardId( nStorFmt );
                            nReturn = ERRCODE_SFX_FORCEQUIET;
                        }
                    }
                    else if ( (*pFilter)->GetFilterContainer() == pImpr)
                    {
                        if(SvtModuleOptions().IsImpress())
                        {
                            pFilt = pImpr->GetFilter4ClipBoardId( nStorFmt );
                            nReturn = ERRCODE_SFX_FORCEQUIET;
                        }
                        else
                        {
                            pFilt = pDraw->GetFilter4ClipBoardId( nStorFmt );
                            nReturn = ERRCODE_SFX_FORCEQUIET;
                        }
                    }
                }
                else if(SvtModuleOptions().IsImpress())
                {
                    pFilt = pImpr->GetFilter4ClipBoardId( nStorFmt );
                    nReturn = ERRCODE_NONE;
                }
                else if(SvtModuleOptions().IsDraw())
                {
                    pFilt = pDraw->GetFilter4ClipBoardId( nStorFmt );
                    nReturn = ERRCODE_NONE;
                }

                if (pFilt &&
                    (pFilt->GetFilterFlags() & nMust) == nMust &&
                    (pFilt->GetFilterFlags() & nDont) == 0)
                {
                    *pFilter = pFilt;
                }
                else
                {
                    *pFilter = NULL;
                    nReturn = ERRCODE_NONE;
                }
            }
            else if(SvtModuleOptions().IsImpress())
            {
                // Erkennung ueber contained streams (PowerPoint 97-Filter)
                String aStreamName = UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "PowerPoint Document" ) );

                if (pStorage->IsContained( aStreamName ) && pStorage->IsStream( aStreamName ) )
                {
                    String aFileName(rMedium.GetName());
                    aFileName.ToUpperAscii();

                    if( aFileName.SearchAscii( ".POT" ) == STRING_NOTFOUND )
                        *pFilter = SFX_APP()->GetFilter(SdDrawDocShell::Factory(), pFilterPowerPoint97);
                    else
                        *pFilter = SFX_APP()->GetFilter(SdDrawDocShell::Factory(), pFilterPowerPoint97Template);

                    return ERRCODE_NONE;
                }
            }
        }

        // XML filter(s)
        if( *pFilter )
        {
            ::rtl::OUString aName = (*pFilter)->GetFilterName();

            if( aName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("StarOffice XML (Draw)")) ||
                aName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("StarOffice XML (Impress)")) ||
                aName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("draw_StarOffice_XML_Impress")) ||
                aName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("impress_StarOffice_XML_Draw")) ||
                aName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("impress_StarOffice_XML_Impress_Template")) ||
                aName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("draw_StarOffice_XML_Draw_Template")) ||
                aName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("draw_StarOffice_XML_Draw")) ||
                aName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("impress_StarOffice_XML_Impress")))
            {
                if( rMedium.IsStorage() )
                {
                    SvStorage* pStorage = rMedium.GetStorage();

                    nReturn = ERRCODE_ABORT;

                    if( pStorage && ( pStorage->IsStream( pStarDrawXMLContent ) || pStorage->IsStream( pStarDrawOldXMLContent ) ) )
                    {
                        const ULONG nStorageFormat = pStorage->GetFormat();
                        if( nStorageFormat == 0 ||
                            nStorageFormat == SOT_FORMATSTR_ID_STARIMPRESS_60 ||
                            nStorageFormat == SOT_FORMATSTR_ID_STARDRAW_60  )
                        {
                            nReturn = ERRCODE_NONE;
                        }
                    }
                }
            }
        }

        String aFileName(rMedium.GetName());
        aFileName.ToUpperAscii();

        if (nReturn == ERRCODE_ABORT)
        {
            if( bStorage )         // aber keine Clipboard-Id #55337#
            {
                *pFilter = NULL;
            }
            else
            {
                // Vektorgraphik?
                SvStream* pStm = rMedium.GetInStream();

                if( !pStm )
                    nReturn = ERRCODE_IO_GENERAL;
                else
                {
                    pStm->Seek( STREAM_SEEK_TO_BEGIN );

                    const String        aLclFileName( rMedium.GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) );
                    GraphicDescriptor   aDesc( *pStm, &aLclFileName );
                    GraphicFilter*      pGrfFilter = GetGrfFilter();

                    if( !aDesc.Detect( FALSE ) )
                    {
                        *pFilter = NULL;
                        nReturn = ERRCODE_ABORT;
                        INetURLObject aURL( aLclFileName );
                        if( aURL.getExtension().equalsIgnoreAsciiCaseAscii( "cgm" ) )
                        {
                            sal_uInt8 n8;
                            pStm->Seek( STREAM_SEEK_TO_BEGIN );
                            *pStm >> n8;
                            if ( ( n8 & 0xf0 ) == 0 )       // we are supporting binary cgm format only, so
                            {                               // this is a small test to exclude cgm text
                                const String aName = UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "CGM - Computer Graphics Metafile" ) );
                                *pFilter = SFX_APP()->GetFilter( SdDrawDocShell::Factory(), aName );
                                nReturn = ERRCODE_NONE;
                            }
                        }
                    }
                    else
                    {
                        if( SvtModuleOptions().IsDraw() )
                        {
                            String aShortName( aDesc.GetImportFormatShortName( aDesc.GetFileFormat() ) );
                            const String aName( pGrfFilter->GetImportFormatTypeName( pGrfFilter->GetImportFormatNumberForShortName( aShortName ) ) );

                            if ( *pFilter && aShortName.EqualsIgnoreCaseAscii( "PCD" ) )    // there is a multiple pcd selection possible
                            {
                                sal_Int32 nBase = 2;    // default Base0
                                String aFilterTypeName( (*pFilter)->GetRealTypeName() );
                                if ( aFilterTypeName.CompareToAscii( "pcd_Photo_CD_Base4" ) == COMPARE_EQUAL )
                                    nBase = 1;
                                else if ( aFilterTypeName.CompareToAscii( "pcd_Photo_CD_Base16" ) == COMPARE_EQUAL )
                                    nBase = 0;
                                String aFilterConfigPath( RTL_CONSTASCII_USTRINGPARAM( "Office.Common/Filter/Graphic/Import/PCD" ) );
                                FilterConfigItem aFilterConfigItem( aFilterConfigPath );
                                aFilterConfigItem.WriteInt32( String( RTL_CONSTASCII_USTRINGPARAM( "Resolution" ) ), nBase );
                            }

                            *pFilter = SFX_APP()->GetFilter( SdGraphicDocShell::Factory(), aName );
                            nReturn = ERRCODE_NONE;
                        }
                        else
                        {
                            nReturn = ERRCODE_ABORT;
                            *pFilter = NULL;
                        }
                    }
                }
            }
        }
    }
    else
    {
        nReturn = rMedium.GetError();
    }

    return nReturn;
}



/*************************************************************************
|*
|* Modul laden
|*
\************************************************************************/

SfxModule* SdModuleDummy::Load()
{
    return (LoadLibSd() ? SD_MOD() : NULL);
}

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
