/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: childwin.cxx,v $
 *
 *  $Revision: 1.21 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 17:37:19 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#ifndef _TOOLBOX_HXX //autogen
#include <vcl/toolbox.hxx>
#endif
#ifndef _RCID_H
#include <tools/rcid.h>
#endif
#ifndef INCLUDED_SVTOOLS_VIEWOPTIONS_HXX
#include <svtools/viewoptions.hxx>
#endif

#ifndef _COM_SUN_STAR_FRAME_XCONTROLLER_HPP_
#include <com/sun/star/frame/XController.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
#include <com/sun/star/frame/XFrame.hpp>
#endif
#ifndef _COM_SUN_STAR_UTIL_XCLOSEABLE_HPP_
#include <com/sun/star/util/XCloseable.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif

#ifndef GCC
#pragma hdrstop
#endif

#include "childwin.hxx"
#include "app.hxx"
#include "arrdecl.hxx"
#include "bindings.hxx"
#include "module.hxx"
#include "dockwin.hxx"
#include "dispatch.hxx"
#include "appdata.hxx"
#include <workwin.hxx>

static const sal_uInt16 nVersion = 2;

DBG_NAME(SfxChildWindow)

SV_IMPL_PTRARR( SfxChildWinContextArr_Impl, SfxChildWinContextFactory* );

struct SfxChildWindow_Impl
{
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >             xFrame;
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >      xListener;
    SfxChildWinFactory* pFact;
    sal_Bool                bHideNotDelete;
    sal_Bool                bVisible;
    sal_Bool                bHideAtToggle;
    sal_Bool                bWantsFocus;
    SfxModule*          pContextModule;
    SfxWorkWindow*      pWorkWin;
};

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

class DisposeListener : public ::cppu::WeakImplHelper1< ::com::sun::star::lang::XEventListener >
{
    public:
        DisposeListener( SfxChildWindow*      pOwner ,
                         SfxChildWindow_Impl* pData  )
            :   m_pOwner( pOwner )
            ,   m_pData ( pData  )
        {}

        virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& aSource ) throw (::com::sun::star::uno::RuntimeException)
        {
            ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener > xSelfHold( this );

            ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > xComp( aSource.Source, ::com::sun::star::uno::UNO_QUERY );
            if( xComp.is() )
                xComp->removeEventListener( this );

            if( m_pOwner && m_pData )
            {
                m_pData->xListener = ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >();

                if ( m_pData->pWorkWin )
                {
                    // m_pOwner and m_pData will be killed
                    m_pData->xFrame    = ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >();
                    m_pData->pWorkWin->GetBindings().Execute( m_pOwner->GetType() );
                }
                else
                {
                    delete m_pOwner;
                }

                m_pOwner = NULL;
                m_pData  = NULL;
            }
        }

    private:
        SfxChildWindow*      m_pOwner;
        SfxChildWindow_Impl* m_pData ;
};

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

sal_Bool GetPosSizeFromString( const String& rStr, Point& rPos, Size& rSize )
{
    if ( rStr.GetTokenCount('/') != 4 )
        return sal_False;

    xub_StrLen nIdx = 0;
    rPos.X() = rStr.GetToken(0, '/', nIdx).ToInt32();
    rPos.Y() = rStr.GetToken(0, '/', nIdx).ToInt32();
    rSize.Width() = rStr.GetToken(0, '/', nIdx).ToInt32();
    rSize.Height() = rStr.GetToken(0, '/', nIdx).ToInt32();

    // negative sizes are invalid
    if ( rSize.Width() < 0 || rSize.Height() < 0 )
        return sal_False;

    return sal_True;
}

sal_Bool GetSplitSizeFromString( const String& rStr, Size& rSize )
{
    sal_Int32 nIndex = rStr.Search( ',' );
    if (( nIndex >= 0 ) && ( nIndex < rStr.Len()))
    {
        String aStr = rStr.Copy( nIndex+1 );

        sal_Int32 nCount = aStr.GetTokenCount(';');
        if ( nCount != 2 )
            return sal_False;

        rSize.Width() = aStr.GetToken(0, ';' ).ToInt32();
        rSize.Height() = aStr.GetToken(1, ';' ).ToInt32();

        // negative sizes are invalid
        if ( rSize.Width() < 0 || rSize.Height() < 0 )
            return sal_False;

        return sal_True;
    }

    return sal_False;
}

//=========================================================================
SfxChildWindow::SfxChildWindow(Window *pParentWindow, sal_uInt16 nId)
    : pParent(pParentWindow)
    , nType(nId)
    , eChildAlignment(SFX_ALIGN_NOALIGNMENT)
    , pWindow(0L)
{
    pImp = new SfxChildWindow_Impl;
    pImp->pFact = 0L;
    pImp->bHideNotDelete = sal_False;
    pImp->bHideAtToggle = sal_False;
    pImp->bWantsFocus = sal_True;
    pImp->bVisible = sal_True;
    pImp->pContextModule = NULL;
    pImp->pWorkWin = NULL;

    pContext = 0L;
    DBG_CTOR(SfxChildWindow,0);
}

void SfxChildWindow::Destroy()
{
    if ( GetFrame().is() )
    {
        pImp->pWorkWin = NULL;
        try
        {
            ::com::sun::star::uno::Reference < ::com::sun::star::util::XCloseable > xClose( GetFrame(), ::com::sun::star::uno::UNO_QUERY );
            if ( xClose.is() )
                xClose->close( sal_True );
            else
                GetFrame()->dispose();
        }
        catch ( com::sun::star::uno::Exception& )
        {
        }
    }
    else
        delete this;
}

//-------------------------------------------------------------------------
SfxChildWindow::~SfxChildWindow()
{
    DBG_DTOR(SfxChildWindow,0);
    if ( pContext )
        delete pContext;
    if ( pWindow )
        delete pWindow;
    delete pImp;
}

//-------------------------------------------------------------------------
SfxChildWindow* SfxChildWindow::CreateChildWindow( sal_uInt16 nId,
        Window *pParent, SfxBindings* pBindings, SfxChildWinInfo& rInfo)
{
    SfxChildWindow *pChild=0;
    SfxChildWinFactory* pFact=0;
    sal_uInt16 nOldMode = Application::GetSystemWindowMode();

    // Zuerst ChildWindow im SDT suchen; "Uberlagerungen m"ussen mit einem
    // ChildWindowContext realisiert werden
    SfxApplication *pApp = SFX_APP();
    SfxChildWinFactArr_Impl &rFactories = pApp->GetChildWinFactories_Impl();
    for ( sal_uInt16 nFactory = 0; nFactory < rFactories.Count(); ++nFactory )
    {
        pFact = rFactories[nFactory];
        if ( pFact->nId == nId )
        {
            SfxChildWinInfo& rFactInfo = pFact->aInfo;
            if ( rInfo.bVisible )
            {
                if ( pBindings )
                    pBindings->ENTERREGISTRATIONS();
                rFactInfo.nFlags |= rInfo.nFlags & SFX_CHILDWIN_FORCEDOCK;
                SfxChildWinInfo aInfo = rFactInfo;
                Application::SetSystemWindowMode( SYSTEMWINDOW_MODE_NOAUTOMODE );
                pChild = pFact->pCtor( pParent, nId, pBindings, &aInfo );
                Application::SetSystemWindowMode( nOldMode );
                rFactInfo.nFlags &= ~(rInfo.nFlags & SFX_CHILDWIN_FORCEDOCK );
                if ( pBindings )
                    pBindings->LEAVEREGISTRATIONS();
            }

            break;
        }
    }

    SfxDispatcher *pDisp = pBindings->GetDispatcher_Impl();
    SfxModule *pMod = pDisp ? pApp->GetActiveModule( pDisp->GetFrame() ) :0;
    if ( !pChild &&  pMod )
    {
        SfxChildWinFactArr_Impl *pFactories = pMod->GetChildWinFactories_Impl();
        if ( pFactories )
        {
            SfxChildWinFactArr_Impl &rFactories = *pFactories;
            for ( sal_uInt16 nFactory = 0; nFactory < rFactories.Count(); ++nFactory )
            {
                pFact = rFactories[nFactory];
                if ( pFact->nId == nId )
                {
                    SfxChildWinInfo& rFactInfo = pFact->aInfo;
                    if ( rInfo.bVisible )
                    {
                        if ( pBindings )
                            pBindings->ENTERREGISTRATIONS();
                        rFactInfo.nFlags |= rInfo.nFlags & SFX_CHILDWIN_FORCEDOCK;
                        SfxChildWinInfo aInfo = rFactInfo;
                        Application::SetSystemWindowMode( SYSTEMWINDOW_MODE_NOAUTOMODE );
                        pChild = pFact->pCtor( pParent, nId, pBindings, &aInfo );
                        Application::SetSystemWindowMode( nOldMode );
                        rFactInfo.nFlags &= ~(rInfo.nFlags & SFX_CHILDWIN_FORCEDOCK );
                        if ( pBindings )
                            pBindings->LEAVEREGISTRATIONS();
                    }

                    break;
                }
            }
        }
    }

    if ( pChild )
        pChild->SetFactory_Impl( pFact );

    DBG_ASSERT(pFact && (pChild || !rInfo.bVisible), "ChildWindow-Typ nicht registriert!");

    if ( pChild && !pChild->pWindow )
    {
        DELETEZ(pChild);
        DBG_WARNING("ChildWindow hat kein Fenster!");
    }

    return pChild;
}

//-------------------------------------------------------------------------
void SfxChildWindow::SaveStatus(const SfxChildWinInfo& rInfo)
{
    sal_uInt16 nID = GetType();

    String aWinData( 'V' );
    aWinData += String::CreateFromInt32( nVersion );
    aWinData += ',';
    aWinData += rInfo.bVisible ? 'V' : 'H';
    aWinData += ',';
    aWinData += String::CreateFromInt32( rInfo.nFlags );
    if ( rInfo.aExtraString.Len() )
    {
        aWinData += ',';
        aWinData += rInfo.aExtraString;
    }

    SvtViewOptions aWinOpt( E_WINDOW, String::CreateFromInt32( nID ) );
    // aWinOpt.SetPosition( rInfo.aPos.X(), rInfo.aPos.Y() );
    // aWinOpt.SetSize( rInfo.aSize.Width(), rInfo.aSize.Height() );
    aWinOpt.SetWindowState( String( rInfo.aWinState, RTL_TEXTENCODING_UTF8 ) );

    ::com::sun::star::uno::Sequence < ::com::sun::star::beans::NamedValue > aSeq(1);
    aSeq[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Data") );
    aSeq[0].Value <<= ::rtl::OUString( aWinData );
    aWinOpt.SetUserData( aSeq );

    // ... but save status at runtime!
    pImp->pFact->aInfo = rInfo;
}

//-------------------------------------------------------------------------
void SfxChildWindow::SetAlignment(SfxChildAlignment eAlign)
{
    DBG_CHKTHIS(SfxChildWindow,0);

    eChildAlignment = eAlign;
}

//-------------------------------------------------------------------------
void SfxChildWindow::SetPosSizePixel(const Point& rPoint, Size& rSize)
{
    DBG_CHKTHIS(SfxChildWindow,0);

    pWindow->SetPosSizePixel(rPoint, rSize);
}

//-------------------------------------------------------------------------
SfxChildWinInfo SfxChildWindow::GetInfo() const
{
    DBG_CHKTHIS(SfxChildWindow,0);

    SfxChildWinInfo aInfo;
    aInfo.aPos  = pWindow->GetPosPixel();
    aInfo.aSize = pWindow->GetSizePixel();
    if ( pWindow->IsSystemWindow() )
    {
        ULONG nMask = WINDOWSTATE_MASK_POS | WINDOWSTATE_MASK_STATE;
        if ( pWindow->GetStyle() & WB_SIZEABLE )
            nMask |= ( WINDOWSTATE_MASK_WIDTH | WINDOWSTATE_MASK_HEIGHT );
        aInfo.aWinState = ((SystemWindow*)pWindow)->GetWindowState( nMask );
    }
    else if ( pWindow->GetType() == RSC_DOCKINGWINDOW )
    {
        if (((DockingWindow*)pWindow)->GetFloatingWindow() )
            aInfo.aWinState = ((DockingWindow*)pWindow)->GetFloatingWindow()->GetWindowState();
        else
        {
            SfxChildWinInfo aTmpInfo;
            ((SfxDockingWindow*)pWindow)->FillInfo( aTmpInfo );
            aInfo.aExtraString = aTmpInfo.aExtraString;
        }
    }

    aInfo.bVisible = pImp->bVisible;
    aInfo.nFlags = 0;
    return aInfo;
}

//-------------------------------------------------------------------------
sal_uInt16 SfxChildWindow::GetPosition()
{
    return pImp->pFact->nPos;
}

#if 0
static void ImplWindowStateFromStr( Point rPos, Size rSize, const ByteString& rStr )
{
    ULONG       nValidMask  = 0;
    xub_StrLen  nIndex      = 0;
    ByteString  aTokenStr;

    aTokenStr = rStr.GetToken( 0, ',', nIndex );
    if ( aTokenStr.Len() )
    {
        rPos.X() = aTokenStr.ToInt32();
        nValidMask |= WINDOWSTATE_MASK_X;
    }

    aTokenStr = rStr.GetToken( 0, ',', nIndex );
    if ( aTokenStr.Len() )
    {
        rPos.Y() = aTokenStr.ToInt32();
        nValidMask |= WINDOWSTATE_MASK_Y;
    }

    aTokenStr = rStr.GetToken( 0, ',', nIndex );
    if ( aTokenStr.Len() )
    {
        rSize.Width() = aTokenStr.ToInt32();
        nValidMask |= WINDOWSTATE_MASK_WIDTH;
    }

    aTokenStr = rStr.GetToken( 0, ';', nIndex );
    if ( aTokenStr.Len() )
    {
        rSize.Height() = aTokenStr.ToInt32();
        nValidMask |= WINDOWSTATE_MASK_HEIGHT;
    }
}
#endif

//-------------------------------------------------------------------------
void SfxChildWindow::InitializeChildWinFactory_Impl( sal_uInt16 nId, SfxChildWinInfo& rInfo )
{
    // load configuration
    SvtViewOptions aWinOpt( E_WINDOW, String::CreateFromInt32( nId ) );

    if ( aWinOpt.Exists() )
        rInfo.bVisible  = aWinOpt.IsVisible(); // set state from configuration. Can be overwritten by UserData, see below

    ::com::sun::star::uno::Sequence < ::com::sun::star::beans::NamedValue > aSeq = aWinOpt.GetUserData();

    ::rtl::OUString aTmp;
    if ( aSeq.getLength() )
        aSeq[0].Value >>= aTmp;

    String aWinData( aTmp );
    rInfo.aWinState = ByteString( String(aWinOpt.GetWindowState()), RTL_TEXTENCODING_UTF8 );

    //ImplWindowStateFromStr( rInfo.aPos, rInfo.aSize, ByteString( aWinState, RTL_TEXTENCODING_UTF8 ) );

    if ( aWinData.Len() )
    {
        // Nach Versionskennung suchen
        if ( aWinData.GetChar((sal_uInt16)0) != 0x0056 ) // 'V' = 56h
            // Keine Versionskennung, daher nicht verwenden
            return;

        // 'V' l"oschen
        aWinData.Erase(0,1);

        // Version lesen
        char cToken = ',';
        sal_uInt16 nPos = aWinData.Search( cToken );
        sal_uInt16 nActVersion = (sal_uInt16)aWinData.Copy( 0, nPos + 1 ).ToInt32();
        if ( nActVersion != nVersion )
            return;

        aWinData.Erase(0,nPos+1);

        //aWinOpt.GetPosition( rInfo.aPos.X(), rInfo.aPos.Y() );
        //aWinOpt.GetSize( rInfo.aSize.Width(), rInfo.aSize.Height() );

        // Sichtbarkeit laden: ist als ein char codiert
        rInfo.bVisible = (aWinData.GetChar(0) == 0x0056); // 'V' = 56h
        aWinData.Erase(0,1);
        nPos = aWinData.Search( cToken );
        if (nPos != STRING_NOTFOUND)
        {
            USHORT nNextPos = aWinData.Search( cToken, 2 );
            if ( nNextPos != STRING_NOTFOUND )
            {
                // es gibt noch Extra-Information
                rInfo.nFlags = (sal_uInt16)aWinData.Copy( nPos+1, nNextPos - nPos - 1 ).ToInt32();
                aWinData.Erase( nPos, nNextPos-nPos+1 );
                rInfo.aExtraString = aWinData;
            }
            else
                rInfo.nFlags = (sal_uInt16)aWinData.Copy( nPos+1 ).ToInt32();
        }
    }
}

void SfxChildWindow::CreateContext( sal_uInt16 nContextId, SfxBindings& rBindings )
{
    SfxChildWindowContext *pCon = NULL;
    SfxChildWinFactory* pFact=0;
    SfxApplication *pApp = SFX_APP();
    SfxDispatcher *pDisp = rBindings.GetDispatcher_Impl();
    SfxModule *pMod = pDisp ? pApp->GetActiveModule( pDisp->GetFrame() ) :0;
    if ( pMod )
    {
        SfxChildWinFactArr_Impl *pFactories = pMod->GetChildWinFactories_Impl();
        if ( pFactories )
        {
            SfxChildWinFactArr_Impl &rFactories = *pFactories;
            for ( sal_uInt16 nFactory = 0; nFactory < rFactories.Count(); ++nFactory )
            {
                pFact = rFactories[nFactory];
                if ( pFact->nId == GetType() )
                {
                    DBG_ASSERT( pFact->pArr, "Kein Kontext angemeldet!" );
                    if ( !pFact->pArr )
                        break;

                    SfxChildWinContextFactory *pConFact=0;
                    for ( sal_uInt16 n=0; n<pFact->pArr->Count(); ++n )
                    {
                        pConFact = (*pFact->pArr)[n];
                        rBindings.ENTERREGISTRATIONS();
                        if ( pConFact->nContextId == nContextId )
                        {
                            SfxChildWinInfo aInfo = pFact->aInfo;
                            pCon = pConFact->pCtor( GetWindow(), &rBindings, &aInfo );
                            pCon->nContextId = pConFact->nContextId;
                            pImp->pContextModule = pMod;
                        }
                        rBindings.LEAVEREGISTRATIONS();
                    }
                    break;
                }
            }
        }
    }

    if ( !pCon )
    {
        SfxChildWinFactArr_Impl &rFactories = pApp->GetChildWinFactories_Impl();
        for ( sal_uInt16 nFactory = 0; nFactory < rFactories.Count(); ++nFactory )
        {
            pFact = rFactories[nFactory];
            if ( pFact->nId == GetType() )
            {
                DBG_ASSERT( pFact->pArr, "Kein Kontext angemeldet!" );
                if ( !pFact->pArr )
                    break;

                SfxChildWinContextFactory *pConFact=0;
                for ( sal_uInt16 n=0; n<pFact->pArr->Count(); ++n )
                {
                    pConFact = (*pFact->pArr)[n];
                    rBindings.ENTERREGISTRATIONS();
                    if ( pConFact->nContextId == nContextId )
                    {
                        SfxChildWinInfo aInfo = pFact->aInfo;
                        pCon = pConFact->pCtor( GetWindow(), &rBindings, &aInfo );
                        pCon->nContextId = pConFact->nContextId;
                        pImp->pContextModule = NULL;
                    }
                    rBindings.LEAVEREGISTRATIONS();
                }
                break;
            }
        }
    }

    if ( !pCon )
    {
        DBG_ERROR( "Kein geeigneter Context gefunden!" );
        return;
    }

    if ( pContext )
        delete( pContext );
    pContext = pCon;
    pContext->GetWindow()->SetSizePixel( pWindow->GetOutputSizePixel() );
    pContext->GetWindow()->Show();
}

SfxChildWindowContext::SfxChildWindowContext( sal_uInt16 nId )
    : pWindow( NULL )
    , nContextId( nId )
{
}

SfxChildWindowContext::~SfxChildWindowContext()
{
    delete pWindow;
}

FloatingWindow* SfxChildWindowContext::GetFloatingWindow() const
{
    Window *pParent = pWindow->GetParent();
    if ( pParent->GetType() == RSC_DOCKINGWINDOW || pParent->GetType() == RSC_TOOLBOX )
    {
        return ((DockingWindow*)pParent)->GetFloatingWindow();
    }
    else if ( pParent->GetType() == RSC_FLOATINGWINDOW )
    {
        return (FloatingWindow*) pParent;
    }
    else
    {
        DBG_ERROR("Kein FloatingWindow-Context!");
        return NULL;
    }
}

SfxChildAlignment SfxChildWindowContext::GetAlignment() const
{
    Window *pParent = pWindow->GetParent();
    if ( pParent->GetType() == RSC_DOCKINGWINDOW )
    {
        return ((SfxDockingWindow*)pParent)->GetAlignment();
    }
    else if ( pParent->GetType() == RSC_TOOLBOX )
    {
        HACK(noch nicht verwendet und noch nicht implementiert);
        return SFX_ALIGN_NOALIGNMENT;
    }
    else
        return SFX_ALIGN_NOALIGNMENT;
}

void SfxChildWindowContext::Resizing( Size& rSize )
{
}

sal_Bool SfxChildWindowContext::Close()
{
    return sal_True;
}

void SfxChildWindow::SetFactory_Impl( SfxChildWinFactory *pF )
{
    pImp->pFact = pF;
}

void SfxChildWindow::SetHideNotDelete( sal_Bool bOn )
{
    pImp->bHideNotDelete = bOn;
}

sal_Bool SfxChildWindow::IsHideNotDelete() const
{
    return pImp->bHideNotDelete;
}

void SfxChildWindow::SetHideAtToggle( sal_Bool bOn )
{
    pImp->bHideAtToggle = bOn;
}

sal_Bool SfxChildWindow::IsHideAtToggle() const
{
    return pImp->bHideAtToggle;
}

void SfxChildWindow::SetWantsFocus( BOOL bSet )
{
    pImp->bWantsFocus = bSet;
}

sal_Bool SfxChildWindow::WantsFocus() const
{
    return pImp->bWantsFocus;
}

sal_Bool SfxChildWinInfo::GetExtraData_Impl
(
    SfxChildAlignment   *pAlign,
    SfxChildAlignment   *pLastAlign,
    Size                *pSize,
    sal_uInt16          *pLine,
    sal_uInt16          *pPos
)   const
{
    // ung"ultig?
    if ( !aExtraString.Len() )
        return sal_False;
    String aStr;
    sal_uInt16 nPos = aExtraString.SearchAscii("AL:");
    if ( nPos == STRING_NOTFOUND )
        return sal_False;

    // Versuche, den Alignment-String "ALIGN:(...)" einzulesen; wenn
    // er nicht vorhanden ist, liegt eine "altere Version vor
    if ( nPos != STRING_NOTFOUND )
    {
        sal_uInt16 n1 = aExtraString.Search('(', nPos);
        if ( n1 != STRING_NOTFOUND )
        {
            sal_uInt16 n2 = aExtraString.Search(')', n1);
            if ( n2 != STRING_NOTFOUND )
            {
                // Alignment-String herausschneiden
                aStr = aExtraString.Copy(nPos, n2 - nPos + 1);
                aStr.Erase(nPos, n1-nPos+1);
            }
        }
    }

    // Zuerst das Alignment extrahieren
    if ( !aStr.Len() )
        return sal_False;
    if ( pAlign )
        *pAlign = (SfxChildAlignment) (sal_uInt16) aStr.ToInt32();

    // Dann das LastAlignment
    nPos = aStr.Search(',');
    if ( nPos == STRING_NOTFOUND )
        return sal_False;
    aStr.Erase(0, nPos+1);
    if ( pLastAlign )
        *pLastAlign = (SfxChildAlignment) (sal_uInt16) aStr.ToInt32();

    // Dann die Splitting-Informationen
    nPos = aStr.Search(',');
    if ( nPos == STRING_NOTFOUND )
        // Dockt nicht in einem Splitwindow
        return sal_True;
    aStr.Erase(0, nPos+1);
    Point aPos;
    Size aSize;
    if ( GetPosSizeFromString( aStr, aPos, aSize ) )
    {
        if ( pSize )
            *pSize = aSize;
        if ( pLine )
            *pLine = (sal_uInt16) aPos.X();
        if ( pPos )
            *pPos = (sal_uInt16) aPos.Y();
        return sal_True;
    }
    return sal_False;
}

sal_Bool SfxChildWindow::IsVisible() const
{
    return pImp->bVisible;
}

void SfxChildWindow::SetVisible_Impl( sal_Bool bVis )
{
    pImp->bVisible = bVis;
}

void SfxChildWindow::Hide()
{
    switch ( pWindow->GetType() )
    {
        case RSC_DOCKINGWINDOW :
            ((DockingWindow*)pWindow)->Hide();
            break;
        case RSC_TOOLBOX :
            ((ToolBox*)pWindow)->Hide();
            break;
        default:
            pWindow->Hide();
            break;
    }
}



void SfxChildWindow::Show( USHORT nFlags )
{
    switch ( pWindow->GetType() )
    {
        case RSC_DOCKINGWINDOW :
            ((DockingWindow*)pWindow)->Show( TRUE, nFlags );
            break;
        case RSC_TOOLBOX :
            ((ToolBox*)pWindow)->Show( TRUE, nFlags );
            break;
        default:
            pWindow->Show( TRUE, nFlags );
            break;
    }
}

Window* SfxChildWindow::GetContextWindow( SfxModule *pModule ) const
{
    return pModule == pImp->pContextModule && pContext ? pContext->GetWindow(): 0;
}

void SfxChildWindow::SetWorkWindow_Impl( SfxWorkWindow* pWin )
{
    pImp->pWorkWin = pWin;
    if ( pWin && pWindow->HasChildPathFocus() )
        pImp->pWorkWin->SetActiveChild_Impl( pWindow );
}

//SfxWorkWindow* SfxChildWindow::GetWorkWindow_Impl() const
//{
//  return pImp->pWorkWin;
//}

void SfxChildWindow::Activate_Impl()
{
    if(pImp->pWorkWin!=NULL) //@#60568#
        pImp->pWorkWin->SetActiveChild_Impl( pWindow );
}

void SfxChildWindow::Deactivate_Impl()
{
//  pImp->pWorkWin->SetActiveChild_Impl( NULL );
}

sal_Bool SfxChildWindow::QueryClose()
{
    sal_Bool bAllow = sal_True;

    if ( pImp->xFrame.is() )
    {
        ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >  xCtrl = pImp->xFrame->getController();
        if ( xCtrl.is() )
            bAllow = xCtrl->suspend( sal_True );
    }

    return bAllow;
}

::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >  SfxChildWindow::GetFrame()
{
    return pImp->xFrame;
}

void SfxChildWindow::SetFrame( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > & rFrame )
{
    // Do nothing if nothing will be changed ...
    if( pImp->xFrame != rFrame )
    {
        // ... but stop listening on old frame, if connection exist!
        if( pImp->xFrame.is() )
            pImp->xFrame->removeEventListener( pImp->xListener );

        // If new frame isnt NULL -> we must guarantee valid listener for disposing events.
        // Use already existing or create new one.
        if( rFrame.is() )
            if( !pImp->xListener.is() )
                pImp->xListener = ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >( new DisposeListener( this, pImp ) );

        // Set new frame in data container
        // and build new listener connection, if neccessary.
        pImp->xFrame = rFrame;
        if( pImp->xFrame.is() )
            pImp->xFrame->addEventListener( pImp->xListener );
    }
}

sal_Bool SfxChildWindow::CanGetFocus() const
{
    return !(pImp->pFact->aInfo.nFlags & SFX_CHILDWIN_CANTGETFOCUS);
}

