/* -*- 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.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sfx2.hxx"
#include <com/sun/star/embed/XStorage.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include "com/sun/star/ui/dialogs/TemplateDescription.hpp"

#include <stdio.h>

#include <svtools/prnsetup.hxx>
#include <vcl/cmdevt.hxx>
#include <vcl/menubtn.hxx>
#include <vcl/msgbox.hxx>
#include <vcl/print.hxx>
#include <svl/style.hxx>
#include <svl/stritem.hxx>
#include <svl/eitem.hxx>
#include <svtools/sfxecode.hxx>
#include <svtools/ehdl.hxx>
#include <svtools/imagemgr.hxx>
#include <vcl/waitobj.hxx>
#include <tools/urlobj.hxx>
#include <tools/color.hxx>
#include <unotools/pathoptions.hxx>
#include <unotools/moduleoptions.hxx>
#include <sot/exchange.hxx>
#include <comphelper/storagehelper.hxx>

#include "helpid.hrc"
#include "docvor.hxx"
#include <sfx2/docfac.hxx>
#include "orgmgr.hxx"
#include <sfx2/doctempl.hxx>
#include <sfx2/templdlg.hxx>
#include "sfxtypes.hxx"
#include <sfx2/app.hxx>
#include <sfx2/dispatch.hxx>
#include "sfxresid.hxx"
#include "doc.hrc"
#include <sfx2/sfx.hrc>
#include "docvor.hrc"
#include <sfx2/docfilt.hxx>
#include <sfx2/filedlghelper.hxx>
#include <sfx2/docfilt.hxx>
#include <sfx2/fcontnr.hxx>
#include <svtools/localresaccess.hxx>
#include <svtools/addresstemplate.hxx>
#include <comphelper/processfactory.hxx>
#define _SVSTDARR_STRINGSDTOR
#include <svl/svstdarr.hxx>

static const char cDelim = ':';
BOOL SfxOrganizeListBox_Impl::bDropMoveOk = TRUE;

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

//=========================================================================

class SuspendAccel
{
public:
    Accelerator*	pAccel;

    SuspendAccel( Accelerator* pA )
    {
        pAccel=pA;
        GetpApp()->RemoveAccel( pAccel );
    }
    ~SuspendAccel()
    {
        GetpApp()->InsertAccel( pAccel );
    }
};

//=========================================================================


inline void SfxOrganizeListBox_Impl::SetBitmaps(
    const Image &rOFolder, const Image &rCFolder, const Image &rODoc, const Image &rCDoc,
    const Image &rOFolderHC, const Image &rCFolderHC, const Image &rODocHC, const Image &rCDocHC )
{
    aOpenedFolderBmp = rOFolder;
    aClosedFolderBmp = rCFolder;
    aOpenedDocBmp = rODoc;
    aClosedDocBmp = rCDoc;

    aOpenedFolderBmpHC = rOFolderHC;
    aClosedFolderBmpHC = rCFolderHC;
    aOpenedDocBmpHC = rODocHC;
    aClosedDocBmpHC = rCDocHC;

}

//=========================================================================

#define NO_DROP_ACTION  ((sal_Int8)-1)

class SfxOrganizeDlg_Impl
{
friend class SfxTemplateOrganizeDlg;
friend class SfxOrganizeListBox_Impl;

    SuspendAccel*			pSuspend;
    SfxTemplateOrganizeDlg* pDialog;

    SfxOrganizeListBox_Impl* pFocusBox;
    Printer*				 pPrt;

    // save pointer for asynchronous D&D
    SvLBox*					pSourceView;
    SvLBoxEntry*			pTargetEntry;
    SfxOrganizeListBox_Impl* pFinishedBox;
    sal_Int8                nDropAction;
    bool                    bExecDropFinished;

    // save some variables for the asynchronous file dialog
    USHORT                  m_nRegion;
    USHORT                  m_nIndex;
    String                  m_sExtension4Save;

    SfxOrganizeListBox_Impl aLeftLb;
    ListBox                 aLeftTypLb;

    SfxOrganizeListBox_Impl aRightLb;
    ListBox                 aRightTypLb;

    OKButton                aOkBtn;
    MenuButton              aEditBtn;
    HelpButton              aHelpBtn;
    PushButton              aAddressTemplateBtn;
    PushButton              aFilesBtn;

    Accelerator             aEditAcc;

    String                  aLastDir;
    SfxOrganizeMgr          aMgr;
    sfx2::FileDialogHelper* pFileDlg;

    SvStringsDtor* 			GetAllFactoryURLs_Impl() const;
    sal_Bool				GetServiceName_Impl( String& rFactoryURL, String& rFileURL ) const;
    long                    Dispatch_Impl( USHORT nId, Menu* _pMenu );
    String                  GetPath_Impl( BOOL bOpen, const String& rFileName );
    ::com::sun::star::uno::Sequence< ::rtl::OUString >
                            GetPaths_Impl( const String& rFileName );
    void					InitBitmaps( void );

    DECL_LINK( GetFocus_Impl, SfxOrganizeListBox_Impl * );
    DECL_LINK( LeftListBoxSelect_Impl, ListBox * );
    DECL_LINK( RightListBoxSelect_Impl, ListBox * );
    DECL_LINK( AccelSelect_Impl, Accelerator * );
    DECL_LINK( MenuSelect_Impl, Menu * );
    DECL_LINK( MenuActivate_Impl, Menu * );
    DECL_LINK( AddFiles_Impl, Button * );
    DECL_LINK( OnAddressTemplateClicked, Button * );

    DECL_LINK( ImportHdl, sfx2::FileDialogHelper* );
    DECL_LINK( ExportHdl, sfx2::FileDialogHelper* );
    DECL_LINK( AddFilesHdl, sfx2::FileDialogHelper* );

    BOOL        DontDelete_Impl( SvLBoxEntry* pEntry );
    void        OkHdl( Button* );

public:
    SfxOrganizeDlg_Impl( SfxTemplateOrganizeDlg* pParent, SfxDocumentTemplates* pTempl );
    ~SfxOrganizeDlg_Impl();
};

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

SfxOrganizeDlg_Impl::SfxOrganizeDlg_Impl( SfxTemplateOrganizeDlg* pParent,
                                          SfxDocumentTemplates* pTempl ) :

    pSuspend            ( NULL ),
    pDialog             ( pParent ),
    pFocusBox           ( NULL ),
    pPrt                ( NULL ),
    pSourceView         ( NULL ),
    pTargetEntry        ( NULL ),
    pFinishedBox        ( NULL ),
    nDropAction         ( NO_DROP_ACTION ),
    bExecDropFinished   ( true ),

    aLeftLb		( this, pParent, WB_BORDER | WB_TABSTOP | WB_HSCROLL, SfxOrganizeListBox_Impl::VIEW_TEMPLATES ),
    aLeftTypLb	(  pParent, SfxResId( LB_LEFT_TYP ) ),

    aRightLb	( this, pParent, WB_BORDER | WB_TABSTOP | WB_HSCROLL, SfxOrganizeListBox_Impl::VIEW_FILES ),
    aRightTypLb	( pParent, SfxResId( LB_RIGHT_TYP ) ),

    aOkBtn				( pParent, SfxResId( BTN_OK ) ),
    aEditBtn			( pParent, SfxResId( BTN_EDIT ) ),
    aHelpBtn			( pParent, SfxResId( BTN_HELP ) ),
    aAddressTemplateBtn	( pParent, SfxResId( BTN_ADDRESSTEMPLATE ) ),
    aFilesBtn			( pParent, SfxResId( BTN_FILES ) ),

    aEditAcc	( SfxResId( ACC_EDIT ) ),
    aMgr        ( &aLeftLb, &aRightLb, pTempl ),
    pFileDlg    ( NULL )

{
    // update the SfxDocumentTemplates the manager works with
    if ( aMgr.GetTemplates() )	// should never fail, but who knows ....
    {
        // for this, show a wait cursor (it may take a while)
        Window* pWaitObjectRange = pDialog ? pDialog->GetParent() : NULL;
        if ( !pWaitObjectRange )
            pWaitObjectRange = pDialog;

        WaitObject aWaitCursor( pWaitObjectRange );
        const_cast< SfxDocumentTemplates* >( aMgr.GetTemplates() )->Update( sal_True /* be smart */ );
            // this const_cast is a hack - but the alternative would be to
            // * have a method which returns the templates non-const
            // * use a new SfxDocumentTemplates instance for the update (knowing that they all share the same
            //	 implementation class)
            // * always work with an own instance, even if we get only NULL in this ctor
    }

    aLeftLb.SetHelpId( HID_CTL_ORGANIZER_LEFT );
    aRightLb.SetHelpId( HID_CTL_ORGANIZER_RIGHT );

    String aWorkPath = SvtPathOptions().GetWorkPath();
    if ( aWorkPath.Len() )
    {
        INetURLObject aObj( aWorkPath );
        DBG_ASSERT( aObj.GetProtocol() != INET_PROT_NOT_VALID, "Illegal URL !" );
        aObj.setFinalSlash();
        aLastDir = aObj.GetMainURL( INetURLObject::DECODE_TO_IURI );
    }
    else
    {
        // fallback
        String aProgURL = SvtPathOptions().SubstituteVariable( String::CreateFromAscii("$(PROGURL)") );
        INetURLObject aObj( aProgURL );
        DBG_ASSERT( aObj.GetProtocol() != INET_PROT_NOT_VALID, "Illegal URL !" );
        aLastDir = aObj.GetMainURL( INetURLObject::DECODE_TO_IURI );
    }

    InitBitmaps();

    aEditBtn.GetPopupMenu()->SetSelectHdl( LINK( this, SfxOrganizeDlg_Impl, MenuSelect_Impl ) );
    aEditBtn.GetPopupMenu()->SetActivateHdl( LINK( this, SfxOrganizeDlg_Impl, MenuActivate_Impl ) );
    aEditAcc.SetSelectHdl( LINK( this, SfxOrganizeDlg_Impl, AccelSelect_Impl ) );
    GetpApp()->InsertAccel( &aEditAcc );

    aFilesBtn.SetClickHdl(
        LINK(this,SfxOrganizeDlg_Impl, AddFiles_Impl));
    aAddressTemplateBtn.SetClickHdl(
        LINK(this,SfxOrganizeDlg_Impl, OnAddressTemplateClicked));
    aLeftTypLb.SetSelectHdl(
        LINK(this, SfxOrganizeDlg_Impl, LeftListBoxSelect_Impl));
    aRightTypLb.SetSelectHdl(
        LINK(this, SfxOrganizeDlg_Impl, RightListBoxSelect_Impl));
    aLeftLb.SetGetFocusHdl(
        LINK(this, SfxOrganizeDlg_Impl, GetFocus_Impl));
    aRightLb.SetGetFocusHdl(
        LINK(this, SfxOrganizeDlg_Impl, GetFocus_Impl));
    aLeftLb.SetPosSizePixel(pParent->LogicToPixel(Point(3, 6), MAP_APPFONT),
                            pParent->LogicToPixel(Size(94, 132), MAP_APPFONT));
    aRightLb.SetPosSizePixel(pParent->LogicToPixel(Point(103, 6), MAP_APPFONT),
                             pParent->LogicToPixel(Size(94, 132), MAP_APPFONT));

    if ( !SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::E_SDATABASE) )
        aAddressTemplateBtn.Hide();
    Font aFont(aLeftLb.GetFont());
    aFont.SetWeight(WEIGHT_NORMAL);
    aLeftLb.SetFont(aFont);
    aRightLb.SetFont(aFont);
    const long nIndent = aLeftLb.GetIndent() / 2;
    aLeftLb.SetIndent( (short)nIndent );
    aRightLb.SetIndent( (short)nIndent );

    aLeftLb.SetMgr(&aMgr);
    aRightLb.SetMgr(&aMgr);
    aLeftLb.Reset();
    aRightLb.Reset();//SetModel(aLeftLb.GetModel());

    aLeftLb.Show();
    aRightLb.Show();

    aLeftLb.SelectAll( FALSE );
    aRightLb.SelectAll( FALSE );
    aRightLb.GrabFocus();
}

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

SfxOrganizeDlg_Impl::~SfxOrganizeDlg_Impl()
{
    delete pFileDlg;
}

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

void SfxOrganizeDlg_Impl::InitBitmaps( void )
{
    Image	aOpenedFolderBmp( SfxResId( IMG_OPENED_FOLDER ) );
    Image	aClosedFolderBmp( SfxResId( IMG_CLOSED_FOLDER ) );
    Image	aOpenedDocBmp( SfxResId( IMG_OPENED_DOC ) );
    Image	aClosedDocBmp( SfxResId( IMG_CLOSED_DOC ) );

    Image	aOpenedFolderBmpHC( SfxResId( IMG_OPENED_FOLDER_HC ) );
    Image	aClosedFolderBmpHC( SfxResId( IMG_CLOSED_FOLDER_HC ) );
    Image	aOpenedDocBmpHC( SfxResId( IMG_OPENED_DOC_HC ) );
    Image	aClosedDocBmpHC( SfxResId( IMG_CLOSED_DOC_HC ) );

    aLeftLb.SetBitmaps( aOpenedFolderBmp, aClosedFolderBmp, aOpenedDocBmp, aClosedDocBmp,
                        aOpenedFolderBmpHC, aClosedFolderBmpHC, aOpenedDocBmpHC, aClosedDocBmpHC );
    aRightLb.SetBitmaps( aOpenedFolderBmp, aClosedFolderBmp, aOpenedDocBmp, aClosedDocBmp,
                        aOpenedFolderBmpHC, aClosedFolderBmpHC, aOpenedDocBmpHC, aClosedDocBmpHC );
}

//=========================================================================

BOOL QueryDelete_Impl(Window *pParent,      // Parent der QueryBox
                             USHORT nId,            // Resource Id
                             const String &rTemplateName)   // Name der zu l"oschenden Vorlage
/*  [Beschreibung]

    "oschabfrage

*/
{
    SfxResId aResId( nId );
    String aEntryText( aResId );
    aEntryText.SearchAndReplaceAscii( "$1", rTemplateName );
    QueryBox aBox( pParent, WB_YES_NO | WB_DEF_NO, aEntryText );
    return RET_NO != aBox.Execute();
}

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

void ErrorDelete_Impl(Window *pParent, const String &rName, sal_Bool bFolder = sal_False )

/*  [Beschreibung]

    Benutzerinformation, da"s die Vorlage rName nicht gel"oscht werden konnte

*/
{
    if ( bFolder )
    {
        String aText( SfxResId( STR_ERROR_DELETE_TEMPLATE_DIR ) );
        ErrorBox( pParent, WB_OK, aText ).Execute();
    }
    else
    {
        String aText( SfxResId( STR_ERROR_DELETE_TEMPLATE ) );
        aText.SearchAndReplaceAscii( "$1", rName );
        ErrorBox( pParent, WB_OK, aText ).Execute();
    }
}


//=========================================================================

/*  [Beschreibung]

    Implementierungsklasse; Referenzklasse f"ur USHORT-Array

*/

struct ImpPath_Impl
{
    SvUShorts	aUS;
    USHORT		nRef;

    ImpPath_Impl();
    ImpPath_Impl( const ImpPath_Impl& rCopy );
};

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

ImpPath_Impl::ImpPath_Impl() : aUS(5), nRef(1)
{
}

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

ImpPath_Impl::ImpPath_Impl( const ImpPath_Impl& rCopy ) :

    aUS	( (BYTE)rCopy.aUS.Count() ),
    nRef( 1 )

{
    const USHORT nCount = rCopy.aUS.Count();

    for ( USHORT i = 0; i < nCount; ++i )
        aUS.Insert( rCopy.aUS[i], i );
}

//==========================================================================

/*  [Beschreibung]

    Implementierungsklasse; Darstellung einer Position in der Outline-
    Listbox als USHORT-Array; dieses beschreibt die Position jeweil
    als relative Postion zum "ubergeordneten Eintrag

*/
class Path
{
    ImpPath_Impl *pData;
    void NewImp();
public:
    Path(SvLBox *pBox, SvLBoxEntry *pEntry);
    Path(const Path &rPath):
        pData(rPath.pData)
    {
        ++pData->nRef;
    }
    const Path &operator=(const Path &rPath)
    {
        if(&rPath != this)
        {
            if(!--pData->nRef)
                delete pData;
            pData = rPath.pData;
            pData->nRef++;
        }
        return *this;
    }
    ~Path()
    {
        if(!--pData->nRef)
            delete pData;
    }
    USHORT Count() const { return pData->aUS.Count(); }
    USHORT operator[]( USHORT i ) const
    {
        return i < Count()? pData->aUS[i]: INDEX_IGNORE;
    }
};

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

Path::Path(SvLBox *pBox, SvLBoxEntry *pEntry) :
    pData(new ImpPath_Impl)
{
    DBG_ASSERT(pEntry != 0, "EntryPtr ist NULL");
    if(!pEntry)
        return;
    SvLBoxEntry *pParent = pBox->GetParent(pEntry);
    do {
        pData->aUS.Insert((USHORT)pBox->GetModel()->GetRelPos(pEntry), 0);
        if(0 == pParent)
            break;
        pEntry = pParent;
        pParent = pBox->GetParent(pEntry);
    } while(1);
}

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

void Path::NewImp()
{
    if(pData->nRef != 1)
    {
        pData->nRef--;
        pData = new ImpPath_Impl(*pData);
    }
}

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

SvLBoxEntry *GetIndices_Impl(SvLBox *pBox,
                               SvLBoxEntry *pEntry,
                               USHORT &rRegion,
                               USHORT &rOffset)
/*  [Beschreibung]

    Bereich und Position innerhalb eines Bereiches f"ur eine
    Dokumentvorlage wird ermittelt.

    [Parameter]

    SvLBox *pBox            Listbox, an der das Ereignis auftrat
    SvLBoxEntry *pEntry     Eintrag, dessen Position ermittelt werden soll
    USHORT &rRegion         der Bereich innerhalb der Bereiche der
                            Dokumentvorlagen (Out-Parameter)
    USHORT &rOffset         die Position innerhalb des Bereiches
                            Dokumentvorlagen (Out-Parameter)

    [Querverweise]

    <class Path>    (unter Umst"anden kann auf diese Funktion zugunsten
                     von Path verzichtet werden.)

*/

{
    if(!pEntry)
    {
        rRegion = rOffset = 0;
        return pEntry;
    }
    if(0 == pBox->GetModel()->GetDepth(pEntry))
    {
        rRegion = (USHORT)pBox->GetModel()->GetRelPos(pEntry);
        rOffset = USHRT_MAX;
        return pEntry;
    }
    SvLBoxEntry *pParent = pBox->GetParent(pEntry);
    rRegion = (USHORT)pBox->GetModel()->GetRelPos(pParent);
    rOffset = (USHORT)pBox->GetModel()->GetRelPos(pEntry);
    return pEntry;
}

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

BOOL SfxOrganizeListBox_Impl::Select( SvLBoxEntry* pEntry, BOOL bSelect )
{
    if(!bSelect)
        return SvTreeListBox::Select(pEntry,bSelect);
    USHORT nLevel = GetDocLevel();
    if(GetModel()->GetDepth(pEntry)+nLevel<3)
        return SvTreeListBox::Select(pEntry,bSelect);

    Path aPath(this, pEntry);
    GetObjectShell(aPath)->TriggerHelpPI(
        aPath[nLevel+1], aPath[nLevel+2], aPath[nLevel+3]);
    return SvTreeListBox::Select(pEntry,bSelect);
}

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

BOOL SfxOrganizeListBox_Impl::MoveOrCopyTemplates(SvLBox *pSourceBox,
                                            SvLBoxEntry *pSource,
                                            SvLBoxEntry* pTarget,
                                            SvLBoxEntry *&pNewParent,
                                            ULONG &rIdx,
                                            BOOL bCopy)
/*  [Beschreibung]

    Verschieben oder Kopieren von Dokumentvorlagen

    [Parameter]

    SvLBox *pSourceBox          Quell-Listbox, an der das Ereignis auftrat
    SvLBoxEntry *pSource        Quell-Eintrag, der kopiert / verschoben werden soll
    SvLBoxEntry* pTarget        Ziel-Eintrag, auf den verschoben werden soll
    SvLBoxEntry *&pNewParent    der Parent der an der Zielposition erzeugten
                                Eintrags (Out-Parameter)
    ULONG &rIdx                 Index des Zieleintrags
    BOOL bCopy                  Flag f"ur Kopieren / Verschieben


    [Returnwert]                BOOL: Erfolg oder Mi"serfolg

    [Querverweise]

    <SfxOrganizeListBox_Impl::MoveOrCopyContents(SvLBox *pSourceBox,
                                            SvLBoxEntry *pSource,
                                            SvLBoxEntry* pTarget,
                                            SvLBoxEntry *&pNewParent,
                                            ULONG &rIdx,
                                            BOOL bCopy)>
    <BOOL SfxOrganizeListBox_Impl::NotifyMoving(SvLBoxEntry *pTarget,
                                            SvLBoxEntry* pSource,
                                            SvLBoxEntry *&pNewParent,
                                            ULONG &rIdx)>
    <BOOL SfxOrganizeListBox_Impl::NotifyCopying(SvLBoxEntry *pTarget,
                                            SvLBoxEntry* pSource,
                                            SvLBoxEntry *&pNewParent,
                                            ULONG &rIdx)>
*/

{
    BOOL bOk = FALSE;

    if(pSource)
    {
        USHORT nTargetRegion = 0, nTargetIndex = 0;
        GetIndices_Impl(this, pTarget, nTargetRegion, nTargetIndex);

        USHORT nSourceRegion = 0, nSourceIndex = 0;
        GetIndices_Impl(pSourceBox, pSource, nSourceRegion, nSourceIndex);

        bOk =  bCopy ?
            pMgr->Copy(nTargetRegion, nTargetIndex+1,
                       nSourceRegion, nSourceIndex):
            pMgr->Move(nTargetRegion, nTargetIndex+1,
                       nSourceRegion, nSourceIndex);

        if(bOk)
        {
            if(pSourceBox->GetModel()->GetDepth(pSource) == GetModel()->GetDepth(pTarget))
            {
                pNewParent = GetParent(pTarget);
                rIdx = GetModel()->GetRelPos(pTarget)+1;
            }
            else
            {
                if(nTargetIndex == USHRT_MAX)
                {
                    pNewParent = pTarget;
                    rIdx = 0;
                }
                else
                    SvLBox::NotifyCopying(
                        pTarget, pSource, pNewParent, rIdx);
            }
        }
        else if ( bCopy )
        {
            // the template organizer always tries copy after the move, so no error is required for move case
            String aText( SfxResId( bCopy ? STR_ERROR_COPY_TEMPLATE : STR_ERROR_MOVE_TEMPLATE ) );
            aText.SearchAndReplaceAscii( "$1",
                                         ( (SvTreeListBox *)pSourceBox )->GetEntryText( pSource ) );
            ErrorBox( this, WB_OK, aText ).Execute();
        }
    }
    return bOk;
}

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

BOOL SfxOrganizeListBox_Impl::MoveOrCopyContents(SvLBox *pSourceBox,
                                            SvLBoxEntry *pSource,
                                            SvLBoxEntry* pTarget,
                                            SvLBoxEntry *&pNewParent,
                                            ULONG &rIdx,
                                            BOOL bCopy)
/*  [Beschreibung]

    Verschieben oder Kopieren von Dokumentinhalten

    [Parameter]

    SvLBox *pSourceBox          Quell-Listbox, an der das Ereignis auftrat
    SvLBoxEntry *pSource        Quell-Eintrag, der kopiert / verschoben werden soll
    SvLBoxEntry* pTarget        Ziel-Eintrag, auf den verschoben werden soll
    SvLBoxEntry *&pNewParent    der Parent der an der Zielposition erzeugten
                                Eintrags (Out-Parameter)
    ULONG &rIdx                 Index des Zieleintrags
    BOOL bCopy                  Flag f"ur Kopieren / Verschieben


    [Returnwert]                BOOL: Erfolg oder Mi"serfolg

    [Querverweise]

    <SfxOrganizeListBox_Impl::MoveOrCopyTemplates(SvLBox *pSourceBox,
                                            SvLBoxEntry *pSource,
                                            SvLBoxEntry* pTarget,
                                            SvLBoxEntry *&pNewParent,
                                            ULONG &rIdx,
                                            BOOL bCopy)>
    <BOOL SfxOrganizeListBox_Impl::NotifyMoving(SvLBoxEntry *pTarget,
                                            SvLBoxEntry* pSource,
                                            SvLBoxEntry *&pNewParent,
                                            ULONG &rIdx)>
    <BOOL SfxOrganizeListBox_Impl::NotifyCopying(SvLBoxEntry *pTarget,
                                            SvLBoxEntry* pSource,
                                            SvLBoxEntry *&pNewParent,
                                            ULONG &rIdx)>
*/

{
    SfxErrorContext aEc( ERRCTX_SFX_MOVEORCOPYCONTENTS, this);
    BOOL bOk = FALSE, bKeepExpansion = FALSE;
    BOOL bRemovedFromSource = FALSE;
    Path aSource(pSourceBox, pSource);
    Path aTarget(this, pTarget);
    SfxObjectShellRef aSourceDoc =
        ((SfxOrganizeListBox_Impl *)pSourceBox)->GetObjectShell(aSource);

    SfxObjectShellRef aTargetDoc = GetObjectShell(aTarget);
    const USHORT nSLevel =
        ((SfxOrganizeListBox_Impl *)pSourceBox)->GetDocLevel();
    const USHORT nTLevel = GetDocLevel();

    if(aSourceDoc.Is() && aTargetDoc.Is())
    {
        if (aSourceDoc->GetStyleSheetPool())
            aSourceDoc->GetStyleSheetPool()->SetSearchMask(
                SFX_STYLE_FAMILY_ALL, SFXSTYLEBIT_USERDEF | SFXSTYLEBIT_USED);

        if (aTargetDoc->GetStyleSheetPool())
            aTargetDoc->GetStyleSheetPool()->SetSearchMask(
                SFX_STYLE_FAMILY_ALL, SFXSTYLEBIT_USERDEF | SFXSTYLEBIT_USED);
        USHORT p[3];
        USHORT nIdxDeleted = INDEX_IGNORE;
        p[0]=aTarget[nTLevel+1];
        p[1]=aTarget[nTLevel+2];
        if(p[1]!=INDEX_IGNORE)p[1]++;
        p[2]=aTarget[nTLevel+3];

        bOk = aTargetDoc->Insert(
            *aSourceDoc, aSource[nSLevel+1],
            aSource[nSLevel+2], aSource[nSLevel+3],
            p[0], p[1], p[2],  nIdxDeleted);
        // Positionskorrektur auswerten
        // a = Dokumentinhalt
        // b = Position Sub-Inhalt 1
        // c = Position Sub-Inhalt 2
        // doppelte Eintraege loeschen
        if(bOk)
        {
            SvLBoxEntry *pParentIter = pTarget;
            // bis auf die DokumentEbene nach oben als
            // allgemeiner Bezugspunkt
            while(GetModel()->GetDepth(pParentIter) != nTLevel)
                pParentIter = GetParent(pParentIter);
            if(pParentIter->HasChildsOnDemand() &&
                !GetModel()->HasChilds(pParentIter))
                RequestingChilds(pParentIter);
            SvLBoxEntry *pChildIter = 0;

            USHORT i = 0;
            while(i < 2 && p[i+1] != INDEX_IGNORE)
            {
                pChildIter = FirstChild(pParentIter);
                // bis zum Index der aktuellen Ebene
                for(USHORT j = 0; j < p[i]; ++j)
                    pChildIter = NextSibling(pChildIter);
                // gfs Fuellen bei Items onDemand
                ++i;
                if(p[i+1] != INDEX_IGNORE &&
                   pChildIter->HasChildsOnDemand() &&
                   !GetModel()->HasChilds(pChildIter))
                    RequestingChilds(pChildIter);
                pParentIter = pChildIter;
            }
            rIdx = p[i];
            pNewParent = pParentIter;
            if(!IsExpanded(pNewParent) &&
               pNewParent->HasChildsOnDemand() &&
               !GetModel()->HasChilds(pNewParent))
            {
                bOk = FALSE;
                if(!bCopy)
                    pSourceBox->GetModel()->Remove(pSource);
            }
            // Geloeschte Eintraege entfernen
            // (kann durch Ueberschreiben geschehen)
            if(nIdxDeleted != INDEX_IGNORE)
            {
                pChildIter = FirstChild(pParentIter);
                for(USHORT j = 0; j < nIdxDeleted; ++j)
                    pChildIter = NextSibling(pChildIter);
                if( pChildIter && pChildIter != pSource )
                {
                    bKeepExpansion = IsExpanded(pParentIter);
                    GetModel()->Remove(pChildIter);
                }
                else
                    bOk = FALSE;
            }
            if(!bCopy && &aSourceDoc != &aTargetDoc)
            {
                //#109566# pool styles that are moved produce
                //an rIdx == INDEX_IGNORE
                //the method has to return true to keep the box content consistent
                bRemovedFromSource = aSourceDoc->Remove(aSource[nSLevel+1],
                                     aSource[nSLevel+2],
                                     aSource[nSLevel+3]);
            }
        }
    }
//  rIdx++;
    return (((rIdx != INDEX_IGNORE)|| bRemovedFromSource) && bOk )
        ? bKeepExpansion? (BOOL)2: TRUE: FALSE;
}

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

BOOL SfxOrganizeListBox_Impl::NotifyMoving(SvLBoxEntry *pTarget,
                                        SvLBoxEntry* pSource,
                                        SvLBoxEntry *&pNewParent,
                                        ULONG &rIdx)

/*  [Beschreibung]

    Benachrichtigung, da"s ein Eintrag verschoben werden soll
    (SV-Handler)

    [Parameter]

    SvLBoxEntry* pTarget        Ziel-Eintrag, auf den verschoben werden soll
    SvLBoxEntry *pSource        Quell-Eintrag, der verschoben werden soll
    SvLBoxEntry *&pNewParent    der Parent der an der Zielposition erzeugten
                                Eintrags (Out-Parameter)
    ULONG &rIdx                 Index des Zieleintrags


    [Returnwert]                BOOL: Erfolg oder Mi"serfolg

    [Querverweise]

    <SfxOrganizeListBox_Impl::MoveOrCopyTemplates(SvLBox *pSourceBox,
                                            SvLBoxEntry *pSource,
                                            SvLBoxEntry* pTarget,
                                            SvLBoxEntry *&pNewParent,
                                            ULONG &rIdx,
                                            BOOL bCopy)>
    <SfxOrganizeListBox_Impl::MoveOrCopyContents(SvLBox *pSourceBox,
                                            SvLBoxEntry *pSource,
                                            SvLBoxEntry* pTarget,
                                            SvLBoxEntry *&pNewParent,
                                            ULONG &rIdx,
                                            BOOL bCopy)>
    <BOOL SfxOrganizeListBox_Impl::NotifyCopying(SvLBoxEntry *pTarget,
                                            SvLBoxEntry* pSource,
                                            SvLBoxEntry *&pNewParent,
                                            ULONG &rIdx)>
*/

{
    BOOL bOk =  FALSE;
    SvLBox* pSourceBox = GetSourceView();
    if ( !pSourceBox )
        pSourceBox = pDlg->pSourceView;
    DBG_ASSERT( pSourceBox, "no source view" );
    if ( !pTarget )
        pTarget = pDlg->pTargetEntry;

    if ( pSourceBox->GetModel()->GetDepth( pSource ) <= GetDocLevel() &&
                      GetModel()->GetDepth( pTarget ) <= GetDocLevel() )
        bOk = MoveOrCopyTemplates( pSourceBox, pSource, pTarget, pNewParent, rIdx, FALSE );
    else
        bOk = MoveOrCopyContents(pSourceBox, pSource, pTarget, pNewParent, rIdx, FALSE );

    return bOk;
}

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

BOOL SfxOrganizeListBox_Impl::NotifyCopying(SvLBoxEntry *pTarget,
                                        SvLBoxEntry* pSource,
                                        SvLBoxEntry *&pNewParent,
                                        ULONG &rIdx)
/*  [Beschreibung]

    Benachrichtigung, da"s ein Eintrag kopiert werden soll
    (SV-Handler)

    [Parameter]

    SvLBoxEntry* pTarget        Ziel-Eintrag, auf den kopiert werden soll
    SvLBoxEntry *pSource        Quell-Eintrag, der kopiert werden soll
    SvLBoxEntry *&pNewParent    der Parent der an der Zielposition erzeugten
                                Eintrags (Out-Parameter)
    ULONG &rIdx                 Index des Zieleintrags


    [Returnwert]                BOOL: Erfolg oder Mi"serfolg

    [Querverweise]

    <SfxOrganizeListBox_Impl::MoveOrCopyTemplates(SvLBox *pSourceBox,
                                            SvLBoxEntry *pSource,
                                            SvLBoxEntry* pTarget,
                                            SvLBoxEntry *&pNewParent,
                                            ULONG &rIdx,
                                            BOOL bCopy)>
    <SfxOrganizeListBox_Impl::MoveOrCopyContents(SvLBox *pSourceBox,
                                            SvLBoxEntry *pSource,
                                            SvLBoxEntry* pTarget,
                                            SvLBoxEntry *&pNewParent,
                                            ULONG &rIdx,
                                            BOOL bCopy)>
    <BOOL SfxOrganizeListBox_Impl::NotifyMoving(SvLBoxEntry *pTarget,
                                            SvLBoxEntry* pSource,
                                            SvLBoxEntry *&pNewParent,
                                            ULONG &rIdx)>
*/
{
    BOOL bOk =  FALSE;
    SvLBox* pSourceBox = GetSourceView();
    if ( !pSourceBox )
        pSourceBox = pDlg->pSourceView;
    DBG_ASSERT( pSourceBox, "no source view" );
    if ( !pTarget )
        pTarget = pDlg->pTargetEntry;
    if ( pSourceBox->GetModel()->GetDepth( pSource ) <= GetDocLevel() &&
                     GetModel()->GetDepth( pTarget ) <= GetDocLevel() )
        bOk = MoveOrCopyTemplates( pSourceBox, pSource, pTarget, pNewParent, rIdx, TRUE );
    else
        bOk = MoveOrCopyContents( pSourceBox, pSource, pTarget, pNewParent, rIdx, TRUE );

    return bOk;
}

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

BOOL SfxOrganizeListBox_Impl::EditingEntry( SvLBoxEntry* pEntry, Selection&  )

/*  [Beschreibung]

    Nachfrage, ob ein Eintrag editierbar ist
    (SV-Handler)

    [Querverweise]
    <SfxOrganizeListBox_Impl::EditedEntry(SvLBoxEntry* pEntry, const String& rText)>
*/

{
    if( VIEW_TEMPLATES == eViewType &&
        GetModel()->GetDepth(pEntry) < 2 )
    {
        pDlg->pSuspend = new SuspendAccel( &pDlg->aEditAcc );
        return TRUE;
    }
    return FALSE;
}

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

BOOL SfxOrganizeListBox_Impl::EditedEntry(SvLBoxEntry* pEntry, const String& rText)

/*  [Beschreibung]

    Der Name eines Eintrags wurde bearbeitet; ist der eingegebene Name
    ein g"ultiger Name ("ange > 0), wird das Model aktualisiert.
    (SV-Handler)

    [Returnwert]

    BOOL                TRUE: der Name soll in der Anzeige ge"andert werden
                        FALSE:der Name soll nicht ge"andert werden

    [Querverweise]
    <SfxOrganizeListBox_Impl::EditingEntry(SvLBoxEntry* pEntry, const String& rText)>
*/

{
    DBG_ASSERT(pEntry, "kein Entry selektiert");
    delete pDlg->pSuspend;
    pDlg->pSuspend = NULL;
    SvLBoxEntry* pParent = GetParent(pEntry);
    if( !rText.Len() )
    {
        ErrorBox aBox( this, SfxResId( MSG_ERROR_EMPTY_NAME ) );
        aBox.GrabFocus();
        aBox.Execute();
        return FALSE;
    }
    if ( !IsUniqName_Impl( rText, pParent, pEntry ) )
    {
        ErrorBox aBox( this, SfxResId( MSG_ERROR_UNIQ_NAME ) );
        aBox.GrabFocus();
        aBox.Execute();
        return FALSE;
    }
    USHORT nRegion = 0, nIndex = 0;
    GetIndices_Impl( this, pEntry, nRegion, nIndex );
    String aOldName;
    if ( USHRT_MAX != nIndex )
        aOldName = pMgr->GetTemplates()->GetName( nRegion, nIndex );
    else
        aOldName = pMgr->GetTemplates()->GetRegionName( nRegion );

    if ( !pMgr->SetName( rText, nRegion, nIndex ) )
    {
        SfxResId aResId( USHRT_MAX != nIndex ? MSG_ERROR_RENAME_TEMPLATE
                                             : MSG_ERROR_RENAME_TEMPLATE_REGION );
        ErrorBox( this, aResId ).Execute();
        return FALSE;
    }
/*
    else
    {
        SfxTemplateOrganizeDlg* pDlg = (SfxTemplateOrganizeDlg*)Window::GetParent();
    }
*/
    return TRUE;
}

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

DragDropMode SfxOrganizeListBox_Impl::NotifyStartDrag( TransferDataContainer&, SvLBoxEntry* pEntry )
{
    USHORT nSourceLevel = GetModel()->GetDepth( pEntry );
    if ( VIEW_FILES == GetViewType() )
        ++nSourceLevel;
    if ( nSourceLevel >= 2 )
        bDropMoveOk = FALSE;
    else
        bDropMoveOk = TRUE;

    return GetDragDropMode();
}

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

BOOL SfxOrganizeListBox_Impl::NotifyAcceptDrop( SvLBoxEntry* pEntry )
{
    if(!pEntry)
        return FALSE;
    SvLBox *pSource = GetSourceView();
    SvLBoxEntry *pSourceEntry = pSource->FirstSelected();
    if(pEntry == pSourceEntry)
        return FALSE;
    USHORT nSourceLevel = pSource->GetModel()->GetDepth(pSourceEntry);
    if(VIEW_FILES == ((SfxOrganizeListBox_Impl *)pSource)->GetViewType())
        ++nSourceLevel;
    USHORT nTargetLevel = GetModel()->GetDepth(pEntry);
    if(VIEW_FILES == GetViewType())
        ++nTargetLevel;
    Path aSource(pSource, pSourceEntry);
    Path aTarget(this, pEntry);
    const USHORT SL = ((SfxOrganizeListBox_Impl *)pSource)->GetDocLevel();
    const USHORT TL = GetDocLevel();

    return( (nSourceLevel == 1 && nTargetLevel == 0 &&
            VIEW_TEMPLATES ==
            ((SfxOrganizeListBox_Impl *)pSource)->GetViewType()) ||
           (nSourceLevel == 1 && nTargetLevel == 1 &&
            VIEW_TEMPLATES ==
            ((SfxOrganizeListBox_Impl *)pSource)->GetViewType() &&
            VIEW_TEMPLATES == GetViewType()) ||
           (nSourceLevel == 3 && nTargetLevel == 1) ||
           (nSourceLevel == 3 && nTargetLevel == 2 &&
            aSource[1+SL] == aTarget[1+TL]) ||
           (nSourceLevel == 3 && nTargetLevel == 3 &&
            aSource[1+SL] == aTarget[1+TL]) ||
           (nSourceLevel == 4 && nTargetLevel == 3 &&
            aSource[1+SL] == aTarget[1+TL] &&
            aSource[2+SL] == aTarget[2+TL]) ||
           (nSourceLevel == 4 && nTargetLevel == 4 &&
            aSource[1+SL] == aTarget[1+TL] &&
            aSource[2+SL] == aTarget[2+TL]));
}

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

sal_Int8 SfxOrganizeListBox_Impl::AcceptDrop( const AcceptDropEvent& rEvt )
{
    sal_Bool bAccept = ( eViewType == VIEW_FILES && IsDropFormatSupported( SOT_FORMAT_FILE ) );
    if ( bAccept )
        return rEvt.mnAction;
    else
        return SvTreeListBox::AcceptDrop( rEvt );
}

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

sal_Int8 SfxOrganizeListBox_Impl::ExecuteDrop( const ExecuteDropEvent& rEvt )
{
    TransferableDataHelper aHelper( rEvt.maDropEvent.Transferable );
    sal_uInt32 nFormatCount = aHelper.GetFormatCount();
    BOOL bSuccess = FALSE;
    for ( sal_uInt32 i = 0; i < nFormatCount; ++i )
    {
        String aFileName;
        SotFormatStringId nId = aHelper.GetFormat(i);

        if ( SOT_FORMAT_FILE == nId && aHelper.GetString( nId, aFileName ) )
        {
            INetURLObject aObj( aFileName, INET_PROT_FILE );
            bSuccess |= pMgr->InsertFile( this, aObj.GetMainURL(INetURLObject::DECODE_TO_IURI) );
        }
    }
    bDropMoveOk = TRUE;
    sal_Int8 nRet = rEvt.mnAction;
    if ( !bSuccess )
    {
        // asynchronous, because of MessBoxes
        pDlg->pSourceView = GetSourceView();
        pDlg->pTargetEntry = pTargetEntry;
        pDlg->pFinishedBox = NULL;
        pDlg->nDropAction = NO_DROP_ACTION;
        PostUserEvent( LINK( this, SfxOrganizeListBox_Impl, OnAsyncExecuteDrop ),
                       new ExecuteDropEvent( rEvt ) );
    }

    return nRet;
}

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

void SfxOrganizeListBox_Impl::DragFinished( sal_Int8 nDropAction )
{
    if ( pDlg->bExecDropFinished )
    {
        if ( pDlg->nDropAction != NO_DROP_ACTION )
            nDropAction = pDlg->nDropAction;
        SvTreeListBox::DragFinished( nDropAction );
        pDlg->nDropAction = NO_DROP_ACTION;
    }
    else
        pDlg->pFinishedBox = this;
}

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

inline USHORT SfxOrganizeListBox_Impl::GetDocLevel() const

/*  [Beschreibung]

    Ermittelt, auf welche Ebene sich Dokumente befinden (unterschiedlich
    in der Dokumentvorlagensicht und der Dokumentensicht)

    [Returnwert]

    USHORT              Die Ebene der Dokumente

*/

{
    return eViewType == VIEW_FILES? 0: 1;
}

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

SfxObjectShellRef SfxOrganizeListBox_Impl::GetObjectShell(const Path &rPath)

/*  [Beschreibung]

    Zugriff auf die ObjectShell, die dem aktuellen Eintrag zugeordnet
    ist.

    [Parameter]

    const Path &rPath       Beschreibung des aktuellen Eintrags

    [Returnwert]

    SfxObjectShellRef     Referenz auf die ObjectShell

    [Querverweise]

    <class Path>

*/

{
    SfxObjectShellRef aDoc;
    if(eViewType == VIEW_FILES)
        aDoc = pMgr->CreateObjectShell(rPath[0]);
    else
        aDoc = pMgr->CreateObjectShell(rPath[0], rPath[1]);
    return aDoc;
}

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

void SfxOrganizeListBox_Impl::RequestingChilds( SvLBoxEntry* pEntry )

/*  [Beschreibung]

    Aufforderung, der Childs eines Eintrags einzuf"ugen
    ist.
    (SV-Handler)

    [Parameter]

    SvLBoxEntry* pEntry     der Eintrag, dessen Childs erfragt werden


*/

{
    // wenn keine Childs vorhanden sind, gfs. Childs
    // einfuegen
    BmpColorMode eColorMode = BMP_COLOR_NORMAL;

    if ( GetSettings().GetStyleSettings().GetHighContrastMode() )
        eColorMode = BMP_COLOR_HIGHCONTRAST;


    if ( !GetModel()->HasChilds( pEntry ) )
    {
        WaitObject aWaitCursor( this );

        // Choose the correct mask color dependent from eColorMode. This must be adopted if
        // we change the mask color for normal images, too!
        Color aMaskColor( COL_LIGHTMAGENTA );

        // hier sind alle initial eingefuegt
        SfxErrorContext aEc(ERRCTX_SFX_CREATEOBJSH, pDlg->pDialog);
        if(VIEW_TEMPLATES == GetViewType() && 0 == GetModel()->GetDepth(pEntry))
        {
            USHORT i = (USHORT)GetModel()->GetRelPos(pEntry);
            const USHORT nEntryCount = pMgr->GetTemplates()->GetCount(i);
            for(USHORT j = 0; j < nEntryCount; ++j)
                InsertEntryByBmpType( pMgr->GetTemplates()->GetName( i, j ), BMPTYPE_DOC, pEntry, TRUE );
        }
        else
        {
            const USHORT nDocLevel = GetDocLevel();
            Path aPath(this, pEntry);
            SfxObjectShellRef aRef = GetObjectShell(aPath);
            if(aRef.Is())
            {
                const USHORT nCount = aRef->GetContentCount(
                    aPath[nDocLevel+1], aPath[nDocLevel+2]);
                String aText;
                Bitmap aClosedBmp, aOpenedBmp;
                const BOOL bCanHaveChilds =
                    aRef->CanHaveChilds(aPath[nDocLevel+1],
                                        aPath[nDocLevel+2]);
                for(USHORT i = 0; i < nCount; ++i)
                {
                    BOOL bDeletable;
                    aRef->GetContent(
                        aText, aClosedBmp, aOpenedBmp, eColorMode, bDeletable,
                        i, aPath[nDocLevel+1], aPath[nDocLevel+2]);

                    // Create image with the correct mask color
                    Image aClosedImage( aClosedBmp, aMaskColor );
                    Image aOpenedImage( aOpenedBmp, aMaskColor );

                    SvLBoxEntry *pNew = SvTreeListBox::InsertEntry(
                        aText, aOpenedImage, aClosedImage,
                        pEntry, bCanHaveChilds);
                    pNew->SetUserData(bDeletable ? &bDeletable : 0);
                }
            }
        }
    }
}

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

long SfxOrganizeListBox_Impl::ExpandingHdl()

/*  [Beschreibung]

    SV-Handler, der nach dem und vor dem Aufklappen eines Eintrags
    gerufen wird.
    Wird verwendet, um gfs. die ObjectShell wieder zu schlie"sen;
    die Eintr"age mit den Inhalten dieser Shell werden ebenfalls
    entfernt.

*/

{
    if ( !(nImpFlags & SVLBOX_IS_EXPANDING) )
    {
        SvLBoxEntry* pEntry  = GetHdlEntry();
        const USHORT nLevel = GetModel()->GetDepth(pEntry);
        if((eViewType == VIEW_FILES && nLevel == 0) ||
           (eViewType == VIEW_TEMPLATES && nLevel == 1))
        {
            Path aPath(this, pEntry);
            // Beim Schliessen des Files die ObjectShell freigeben
            if(eViewType == VIEW_FILES && nLevel == 0)
                pMgr->DeleteObjectShell(aPath[0]);
            else
                pMgr->DeleteObjectShell(aPath[0], aPath[1]);
            // alle SubEntries loeschen
            SvLBoxEntry *pToDel = SvLBox::GetEntry(pEntry, 0);
            while(pToDel)
            {
                GetModel()->Remove(pToDel);
                pToDel = SvLBox::GetEntry(pEntry, 0);
            }
        }
    }
    return TRUE;
}

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

BOOL SfxOrganizeListBox_Impl::IsUniqName_Impl(const String &rText,
                                         SvLBoxEntry* pParent, SvLBoxEntry *pEntry) const

/*  [Beschreibung]

    Pr"uft, ob eine Name auf seiner Ebene eindeutig ist.

    [Parameter]

    const String &         Name des zu suchenden Eintrags
    SvLBoxEntry* pSibling  Geschwister (bezeichnet die Ebene)

    [Returnwert]

    BOOL                     TRUE, wenn der Name eindeutig ist, sonst FALSE
*/

{
    SvLBoxEntry* pChild = FirstChild(pParent);
    while(pChild)  {
        const String aEntryText(GetEntryText(pChild));
        if(COMPARE_EQUAL == aEntryText.CompareIgnoreCaseToAscii(rText)&&(!pEntry || pEntry!=pChild))
            return FALSE;
        pChild = NextSibling(pChild);
    }
    return TRUE;
}

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

USHORT SfxOrganizeListBox_Impl::GetLevelCount_Impl(SvLBoxEntry* pParent) const
{
    SvLBoxEntry* pChild = FirstChild(pParent);
    USHORT nCount = 0;
    while(pChild)  {
        pChild = NextSibling(pChild);
        ++nCount;
    }
    return nCount;
}

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

SvLBoxEntry* SfxOrganizeListBox_Impl::InsertEntryByBmpType( const XubString& rText, BMPTYPE eBmpType,
    SvLBoxEntry* pParent, BOOL bChildsOnDemand, ULONG nPos, void* pUserData )
{
    SvLBoxEntry*	pEntry = NULL;
    const Image*	pExp = NULL;
    const Image*	pCol = NULL;
    const Image*	pExpHC = NULL;
    const Image*	pColHC = NULL;

    switch( eBmpType )
    {
        case BMPTYPE_FOLDER:
            pExp = &aOpenedFolderBmp;
            pCol = &aClosedFolderBmp;
            pExpHC = &aOpenedFolderBmpHC;
            pColHC = &aClosedFolderBmpHC;
            break;
        default:
            DBG_ERROR( "SfxOrganizeListBox_Impl::InsertEntryByBmpType(): something forgotten?!" );

        case BMPTYPE_DOC:
            pExp = &aOpenedDocBmp;
            pCol = &aClosedDocBmp;
            pExpHC = &aOpenedDocBmpHC;
            pColHC = &aClosedDocBmpHC;
            break;
    }

    pEntry = SvTreeListBox::InsertEntry( rText, *pExp, *pCol, pParent, bChildsOnDemand, nPos, pUserData );

    SetExpandedEntryBmp( pEntry, *pExpHC, BMP_COLOR_HIGHCONTRAST );
    SetCollapsedEntryBmp( pEntry, *pColHC, BMP_COLOR_HIGHCONTRAST );

    return pEntry;
}

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

SfxOrganizeListBox_Impl::SfxOrganizeListBox_Impl
(
    SfxOrganizeDlg_Impl* pArgDlg,
    Window* pParent,
    WinBits nBits,
    DataEnum eType
) :

    SvTreeListBox( pParent, nBits ),

    pMgr		( NULL ),
    pDlg		( pArgDlg ),
    eViewType	( eType )

/*  [Beschreibung]

    Konstruktor SfxOrganizeListBox

*/

{
    SetDragDropMode(
        SV_DRAGDROP_CTRL_MOVE | SV_DRAGDROP_CTRL_COPY |
        SV_DRAGDROP_APP_MOVE  | SV_DRAGDROP_APP_COPY  | SV_DRAGDROP_APP_DROP );
    SetEntryHeight( 16 );
    SetSelectionMode( SINGLE_SELECTION );
    GetModel()->SetSortMode( SortNone );

    EnableContextMenuHandling();
}

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

IMPL_LINK( SfxOrganizeListBox_Impl, OnAsyncExecuteDrop, ExecuteDropEvent*, pEvent )
{
    DBG_ASSERT( pEvent, "invalid DropEvent" );
    if ( pEvent )
    {
        SvLBox* pSourceView = GetSourceView();
        if ( !pSourceView )
            pSourceView = pDlg->pSourceView;
        pDlg->bExecDropFinished = false;
        // if a template can not be moved it should be copied
        if ( pEvent->mnAction == DND_ACTION_MOVE )
            pEvent->mnAction = DND_ACTION_COPYMOVE;
        pDlg->nDropAction = SvTreeListBox::ExecuteDrop( *pEvent, pSourceView );
        delete pEvent;
        pDlg->pSourceView = NULL;
        pDlg->pTargetEntry = NULL;
        pDlg->bExecDropFinished = true;
        if ( pDlg->pFinishedBox )
        {
            pDlg->pFinishedBox->DragFinished( pDlg->nDropAction );
            pDlg->pFinishedBox = NULL;
        }
    }
    return 0;
}

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

void SfxOrganizeListBox_Impl::Reset()

/*  [Beschreibung]

    Einf"ugen der Elemente in die ListBox

*/

{
    DBG_ASSERT( pMgr != 0, "kein Manager" );
    // Inhalte l"oschen
    SetUpdateMode(FALSE);
    Clear();
    if ( VIEW_TEMPLATES == eViewType )
    {
        const USHORT nCount = pMgr->GetTemplates()->GetRegionCount();
        for ( USHORT i = 0; i < nCount; ++i )
            InsertEntryByBmpType( pMgr->GetTemplates()->GetFullRegionName(i), BMPTYPE_FOLDER, 0, TRUE );
    }
    else
    {
        const SfxObjectList& rList = pMgr->GetObjectList();
        const USHORT nCount = rList.Count();
        for ( USHORT i = 0; i < nCount; ++i )
            InsertEntryByBmpType( rList.GetBaseName(i), BMPTYPE_DOC, 0, TRUE );

    }
    SetUpdateMode(TRUE);
    Invalidate();
    Update();
}

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

const Image &SfxOrganizeListBox_Impl::GetClosedBmp(USHORT nLevel) const

/*  [Beschreibung]

    Zugriff auf die Bitmap f"ur einen geschlossenen Eintrag
    der jeweiligen Ebene

    [Parameter]

    USHORT nLevel       Angabe der Ebene, 2 Ebenen sind erlaubt

    [Returnwert]

    const Image &       das Image auf der Ebenen nLevel

*/

{
    BOOL			bHC = GetSettings().GetStyleSettings().GetHighContrastMode();
    const Image*	pRet = NULL;

    switch( nLevel )
    {
        default:	DBG_ERROR( "Bitmaps ueberindiziert" );

        case 0:		pRet = bHC? &aClosedFolderBmpHC : &aClosedFolderBmp;		break;
        case 1:		pRet = bHC? &aClosedDocBmpHC : &aClosedDocBmp;				break;
    }

    return *pRet;
}

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

const Image &SfxOrganizeListBox_Impl::GetOpenedBmp(USHORT nLevel) const

/*  [Beschreibung]

    Zugriff auf die Bitmap f"ur einen ge"offneten Eintrag
    der jeweiligen Ebene

    [Parameter]

    USHORT nLevel       Angabe der Ebene, 2 Ebenen sind erlaubt

    [Returnwert]

    const Image &       das Image auf der Ebenen nLevel

*/

{
    BOOL         bHC = GetSettings().GetStyleSettings().GetHighContrastMode();
    const Image* pRet = NULL;

    switch( nLevel )
    {
        case 0:
           pRet = bHC ? &aOpenedFolderBmpHC : &aOpenedFolderBmp; break;
        case 1:
           pRet = bHC ? &aOpenedDocBmpHC : &aOpenedDocBmp; break;
        default:
            pRet = bHC ? &aClosedFolderBmpHC : &aClosedFolderBmp; break;
    }

    return *pRet;
}

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

PopupMenu* SfxOrganizeListBox_Impl::CreateContextMenu()
{
    return new PopupMenu( *( pDlg->aEditBtn.GetPopupMenu() ) );
}

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

String SfxOrganizeDlg_Impl::GetPath_Impl( BOOL bOpen, const String& rFileName )

/*  [Beschreibung]

    Pfad per FileDialog erfragen, f"ur Import / Export von
    Dokumentvorlagen

    [Parameter]

    BOOL bOpen                      Flag: "Offnen / Speichern
    const String& rFileName			aktueller Dateiname als Vorschlag

    [R"uckgabewert]                 Dateiname mit Pfad oder Leerstring, wenn
                                    der Benutzer 'Abbrechen' gedr"uckt hat
*/

{
    String aPath;
    m_sExtension4Save = DEFINE_CONST_UNICODE( "vor" );
    sal_Int16 nDialogType = bOpen
        ? com::sun::star::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE
        : com::sun::star::ui::dialogs::TemplateDescription::FILESAVE_SIMPLE;
    if ( pFileDlg )
        delete pFileDlg;
    pFileDlg = new sfx2::FileDialogHelper( nDialogType, 0L );

    // add "All" filter
    pFileDlg->AddFilter( String( SfxResId( STR_SFX_FILTERNAME_ALL ) ),
                         DEFINE_CONST_UNICODE( FILEDIALOG_FILTER_ALL ) );
    // add template filter
    String sFilterName( SfxResId( STR_TEMPLATE_FILTER ) );
    String sFilterExt;
    // add filters of modules which are installed
    SvtModuleOptions aModuleOpt;
    if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
        sFilterExt += DEFINE_CONST_UNICODE( "*.ott;*.stw;*.oth" );
    if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
    {
        if ( sFilterExt.Len() > 0 )
            sFilterExt += ';';
        sFilterExt += DEFINE_CONST_UNICODE( "*.ots;*.stc" );
    }
    if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
    {
        if ( sFilterExt.Len() > 0 )
            sFilterExt += ';';
        sFilterExt += DEFINE_CONST_UNICODE( "*.otp;*.sti" );
    }
    if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
    {
        if ( sFilterExt.Len() > 0 )
            sFilterExt += ';';
        sFilterExt += DEFINE_CONST_UNICODE( "*.otg;*.std" );
    }
    if ( sFilterExt.Len() > 0 )
        sFilterExt += ';';
    sFilterExt += DEFINE_CONST_UNICODE( "*.vor" );

    sFilterName += DEFINE_CONST_UNICODE( " (" );
    sFilterName += sFilterExt;
    sFilterName += ')';
    pFileDlg->AddFilter( sFilterName, sFilterExt );
    pFileDlg->SetCurrentFilter( sFilterName );

    if ( aLastDir.Len() || rFileName.Len() )
    {
        INetURLObject aObj;
        if ( aLastDir.Len() )
        {
            aObj.SetURL( aLastDir );
            if ( rFileName.Len() )
                aObj.insertName( rFileName );
        }
        else
            aObj.SetURL( rFileName );

        if ( aObj.hasExtension() )
        {
            m_sExtension4Save = aObj.getExtension(
                INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
            aObj.removeExtension();
        }

        DBG_ASSERT( aObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" );
        pFileDlg->SetDisplayDirectory( aObj.GetMainURL( INetURLObject::NO_DECODE ) );
    }

    pFileDlg->StartExecuteModal( LINK( this, SfxOrganizeDlg_Impl, ImportHdl ) );

    return aPath;
}

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

::com::sun::star::uno::Sequence< ::rtl::OUString >
    SfxOrganizeDlg_Impl::GetPaths_Impl( const String& rFileName )

/*  [Description]

   Query plural paths by FileDialog, for Import / Export from document
   templates

   [Parameter]

   const String& rFileName         The default file name when dialog executes

   [Return value]                 Empty sequence when users have clicked
                                  'Cancel', a sequence just containing one
                                  file name with path when they have
                                  choosed one file or a sequence containing
                                  path and file names without path
*/

{
    ::com::sun::star::uno::Sequence< ::rtl::OUString > aPaths;
    m_sExtension4Save = DEFINE_CONST_UNICODE( "vor" );
    if ( pFileDlg )
            delete pFileDlg;
    pFileDlg = new sfx2::FileDialogHelper(
        com::sun::star::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, SFXWB_MULTISELECTION );

    // add "All" filter
    pFileDlg->AddFilter( String( SfxResId( STR_SFX_FILTERNAME_ALL ) ),
                         DEFINE_CONST_UNICODE( FILEDIALOG_FILTER_ALL ) );

    // add template filter
    String sFilterName( SfxResId( STR_TEMPLATE_FILTER ) );
    String sFilterExt;
    // add filters of modules which are installed
    SvtModuleOptions aModuleOpt;
    if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
        sFilterExt += DEFINE_CONST_UNICODE( "*.ott;*.stw;*.oth" );
    if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
    {
        if ( sFilterExt.Len() > 0 )
            sFilterExt += ';';
        sFilterExt += DEFINE_CONST_UNICODE( "*.ots;*.stc" );
    }
    if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
    {
        if ( sFilterExt.Len() > 0 )
            sFilterExt += ';';
        sFilterExt += DEFINE_CONST_UNICODE( "*.otp;*.sti" );
    }
    if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
    {
        if ( sFilterExt.Len() > 0 )
            sFilterExt += ';';
        sFilterExt += DEFINE_CONST_UNICODE( "*.otg;*.std" );
    }
    if ( sFilterExt.Len() > 0 )
        sFilterExt += ';';
    sFilterExt += DEFINE_CONST_UNICODE( "*.vor" );

    sFilterName += DEFINE_CONST_UNICODE( " (" );
    sFilterName += sFilterExt;
    sFilterName += ')';
    pFileDlg->AddFilter( sFilterName, sFilterExt );
    pFileDlg->SetCurrentFilter( sFilterName );

    if ( aLastDir.Len() || rFileName.Len() )
    {
        INetURLObject aObj;
        if ( aLastDir.Len() )
        {
            aObj.SetURL( aLastDir );
            if ( rFileName.Len() )
                aObj.insertName( rFileName );
        }
        else
            aObj.SetURL( rFileName );

        if ( aObj.hasExtension() )
        {
            m_sExtension4Save = aObj.getExtension(
                 INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
            aObj.removeExtension();
        }

        DBG_ASSERT( aObj.GetProtocol() != INET_PROT_NOT_VALID, "Invalid URL!" );
        pFileDlg->SetDisplayDirectory( aObj.GetMainURL( INetURLObject::NO_DECODE ) );
    }

    pFileDlg->StartExecuteModal( LINK( this, SfxOrganizeDlg_Impl, ExportHdl ) );

    return aPaths;
}

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

BOOL SfxOrganizeDlg_Impl::DontDelete_Impl( SvLBoxEntry* pEntry )
{
    USHORT nDepth = pFocusBox->GetModel()->GetDepth(pEntry);
    if(SfxOrganizeListBox_Impl::VIEW_FILES ==
       pFocusBox->GetViewType())
        nDepth++;
    if( (nDepth > 2 && !pEntry->GetUserData()) ||
       //Delete ueber GetContent verboten
       nDepth==2 || //Vorlage / Konfigurtionsrubrik nicht loeshcen
       (nDepth==1 && SfxOrganizeListBox_Impl::VIEW_FILES ==
        pFocusBox->GetViewType()) || //Files nicht loeschen
       (0 == nDepth && pFocusBox->GetLevelCount_Impl(0) < 2))
        //Mindestens eine Vorlage behalten
    {
        return TRUE;
    }

    USHORT nRegion = 0, nIndex = 0;
    GetIndices_Impl( pFocusBox, pEntry, nRegion, nIndex );
    const SfxDocumentTemplates* pTemplates = aMgr.GetTemplates();
    if ( !pTemplates || !pTemplates->HasUserContents( nRegion, nIndex ) )
        return TRUE;

    return FALSE;
}

SvStringsDtor* SfxOrganizeDlg_Impl::GetAllFactoryURLs_Impl( ) const
{
    SvtModuleOptions aModOpt;
    const ::com::sun::star::uno::Sequence < ::rtl::OUString >& aServiceNames = aModOpt.GetAllServiceNames() ;
    SvStringsDtor* pList = new SvStringsDtor;
    sal_Int32 nCount = aServiceNames.getLength();
    for( sal_Int32 i=0; i<nCount; ++i )
    {
        if ( SfxObjectFactory::GetStandardTemplate( aServiceNames[i] ).Len() > 0 )
        {
            SvtModuleOptions::EFactory eFac = SvtModuleOptions::E_WRITER;
            SvtModuleOptions::ClassifyFactoryByName( aServiceNames[i], eFac );
            String* pURL = new String( aModOpt.GetFactoryEmptyDocumentURL( eFac ) );
            pList->Insert( pURL, pList->Count() );
        }
    }

    return pList;
}

sal_Bool SfxOrganizeDlg_Impl::GetServiceName_Impl( String& rName, String& rFileURL ) const
{
    sal_Bool bRet = sal_False;
    const SfxDocumentTemplates*	pTemplates = aMgr.GetTemplates();
    SvLBoxEntry* pEntry = pFocusBox ? pFocusBox->FirstSelected() : NULL;
    USHORT nRegion = 0, nIndex = 0;
    GetIndices_Impl( pFocusBox, pEntry, nRegion, nIndex );
    rFileURL = pTemplates->GetPath( nRegion, nIndex );
    if ( rFileURL.Len() > 0 )
    {
        try
        {
            uno::Reference< embed::XStorage > xStorage = ::comphelper::OStorageHelper::GetStorageFromURL(
                                                    rFileURL,
                                                    embed::ElementModes::READ );
            ULONG nFormat = SotStorage::GetFormatID( xStorage );
            const SfxFilter* pFilter =
                SFX_APP()->GetFilterMatcher().GetFilter4ClipBoardId( nFormat );
            if ( pFilter )
            {
                rName = pFilter->GetServiceName();
                bRet = TRUE;
            }
        }
        catch( uno::Exception& )
        {}
    }

    return bRet;
}

long SfxOrganizeDlg_Impl::Dispatch_Impl( USHORT nId, Menu* _pMenu )

/*  [Beschreibung]

    Verarbeiten der Events aus MenuButton oder Accelerator

    [Parameter]

    USHORT nId                      ID des Events

    [R"uckgabewert]                 1: Event wurde verarbeitet,
                                    0: Event wurde nicht verarbeitet (SV-Menu)

*/

{
    SuspendAccel aTmp(&aEditAcc);
    SvLBoxEntry *pEntry = pFocusBox? pFocusBox->FirstSelected(): 0;
    sal_Bool bHandled = sal_True;
    switch(nId)
    {
        case ID_NEW:
        {
            if(!pEntry)
                return 1;
            if(pFocusBox->GetViewType() == SfxOrganizeListBox_Impl::VIEW_TEMPLATES)
            {
                if(0 == pFocusBox->GetModel()->GetDepth(pEntry))
                {
                    const String aNoName( SfxResId(STR_NONAME) );
                    SvLBoxEntry* pParent = pFocusBox->GetParent(pEntry);
                    String aName(aNoName);
                    USHORT n = 1;
                    while(!pFocusBox->IsUniqName_Impl(aName, pParent))
                    {
                        aName = aNoName;
                        aName += String::CreateFromInt32( n++ );
                    }
                    aMgr.InsertDir( pFocusBox, aName,
                            (USHORT)pFocusBox->GetModel()->GetRelPos(pEntry)+1);
                }
            }
            break;
        }

        case ID_DELETE:
        {
            if(!pEntry || DontDelete_Impl(pEntry))
                return 1;
            const USHORT nDepth = pFocusBox->GetModel()->GetDepth(pEntry);
            if(nDepth < 2)
            {
                if(0 == nDepth && pFocusBox->GetLevelCount_Impl(0) < 2) return 1;
                if(SfxOrganizeListBox_Impl::VIEW_TEMPLATES == pFocusBox->GetViewType())
                {
                    USHORT nResId = nDepth? STR_DELETE_TEMPLATE :
                                            STR_DELETE_REGION;
                    if( !QueryDelete_Impl(
                        pDialog, nResId, pFocusBox->GetEntryText(pEntry)))
                        return 1;
                    if ( STR_DELETE_REGION == nResId &&
                         pFocusBox->GetChildCount(pEntry))
                    {
                        QueryBox aQBox(pDialog, SfxResId(MSG_REGION_NOTEMPTY));
                        if(RET_NO == aQBox.Execute())
                            return 1;
                    }
                    USHORT nRegion = 0, nIndex = 0;
                    GetIndices_Impl(pFocusBox, pEntry, nRegion, nIndex);

                    USHORT nDeleteInd = ( STR_DELETE_REGION == nResId? USHRT_MAX: nIndex );
                    if ( !aMgr.Delete( pFocusBox, nRegion, nDeleteInd ) )
                        ErrorDelete_Impl(
                            pDialog,
                            pFocusBox->GetEntryText(pEntry),
                            ( nDeleteInd == USHRT_MAX && pFocusBox->GetChildCount(pEntry) ) );
                }
            }
            // Inhaltsformen
            else if(nDepth + pFocusBox->GetDocLevel() >= 2)
            {
                if(!QueryDelete_Impl(pDialog, STR_DELETE_TEMPLATE, pFocusBox->GetEntryText(pEntry)))
                    return 1;
                Path aPath(pFocusBox, pEntry);
                SfxObjectShellRef aRef = pFocusBox->GetObjectShell(aPath);
                if(aRef.Is() &&
                    aRef->Remove(aPath[1+pFocusBox->GetDocLevel()],
                                 aPath[2+pFocusBox->GetDocLevel()],
                                 aPath[3+pFocusBox->GetDocLevel()]))
                    pFocusBox->GetModel()->Remove(pEntry);
                else
                    ErrorDelete_Impl(pDialog, pFocusBox->GetEntryText(pEntry), sal_False );
            }
            break;
        }

        case ID_EDIT:
        {
            if(!pEntry)
                return 1;
            USHORT nRegion = 0, nIndex = 0;
            GetIndices_Impl( pFocusBox, pEntry, nRegion, nIndex );
            const SfxStringItem aName( SID_FILE_NAME, aMgr.GetTemplates()->GetPath( nRegion, nIndex ) );
            const SfxStringItem aLongName( SID_FILE_LONGNAME, pFocusBox->GetEntryText( pEntry ) );
            const SfxStringItem aReferer( SID_REFERER, DEFINE_CONST_UNICODE( "private:user" ) );
            const SfxStringItem aTargetName( SID_TARGETNAME, DEFINE_CONST_UNICODE( "_default" ) );
            const SfxBoolItem	aTemplateIndicator( SID_TEMPLATE, sal_False );

            SFX_APP()->GetAppDispatcher_Impl()->Execute( SID_OPENTEMPLATE, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD,
                                      &aName, &aLongName, &aReferer, &aTargetName, &aTemplateIndicator, 0L );
            pDialog->EndDialog( RET_EDIT_STYLE );
            break;
        }

        case ID_COPY_FROM:
        {
            if ( !pEntry )
                return 1;
            m_nRegion = 0;
            m_nIndex = 0;
            GetIndices_Impl( pFocusBox, pEntry, m_nRegion, m_nIndex );
            GetPaths_Impl( String() );
            break;
        }

        case ID_COPY_TO:
        {
            if ( !pEntry )
                return 1;
            m_nRegion = 0;
            m_nIndex = 0;
            GetIndices_Impl( pFocusBox, pEntry, m_nRegion, m_nIndex );
            GetPath_Impl( FALSE, aMgr.GetTemplates()->GetFileName( m_nRegion, m_nIndex ) );
            break;
        }

        case ID_RESCAN:
            if ( !aMgr.Rescan() )
                ErrorBox( pDialog, SfxResId( MSG_ERROR_RESCAN ) ).Execute();
            if ( SfxOrganizeListBox_Impl::VIEW_TEMPLATES == aLeftLb.GetViewType() )
                aLeftLb.Reset();
            if ( SfxOrganizeListBox_Impl::VIEW_TEMPLATES == aRightLb.GetViewType() )
                aRightLb.Reset();
            break;

        case ID_PRINT:
        {
            if ( !pEntry )
                return 1;
            Path aPath( pFocusBox, pEntry );
            SfxObjectShellRef aRef = pFocusBox->GetObjectShell( aPath );
            if ( aRef.Is() )
            {
                const USHORT nDocLevel = pFocusBox->GetDocLevel();
                if ( !pPrt )
                    pPrt = new Printer;
                SvLBoxEntry *pDocEntry = pEntry;
                while ( pFocusBox->GetModel()->GetDepth( pDocEntry ) > nDocLevel )
                    pDocEntry = pFocusBox->GetParent( pDocEntry );
                const String aName(pFocusBox->GetEntryText(pDocEntry));
                if ( !aRef->Print( *pPrt, aPath[1+nDocLevel],
                                   aPath[2+nDocLevel], aPath[3+nDocLevel], &aName ) )
                    ErrorBox( pDialog, SfxResId( MSG_PRINT_ERROR ) ).Execute();
            }
            break;
        }

        case ID_PRINTER_SETUP:
        {
            PrinterSetupDialog* pDlg = new PrinterSetupDialog( pDialog );
            if ( !pPrt )
                pPrt = new Printer;
            pDlg->SetPrinter( pPrt );
            pDlg->Execute();
            delete pDlg;
            break;
        }

        case ID_DEFAULT_TEMPLATE:
        {
            String aServiceName, aFileURL;
            if ( GetServiceName_Impl( aServiceName, aFileURL ) )
                SfxObjectFactory::SetStandardTemplate( aServiceName, aFileURL );
            break;
        }

        default:
            bHandled = sal_False;
    }

    if ( !bHandled && ( nId > ID_RESET_DEFAULT_TEMPLATE || nId <= ID_RESET_DEFAULT_TEMPLATE_END ) )
    {
        Menu* pSubMenu = _pMenu ? _pMenu : aEditBtn.GetPopupMenu()->GetPopupMenu( ID_RESET_DEFAULT_TEMPLATE );
        if ( pSubMenu )
        {
            String aServiceName = SfxObjectShell::GetServiceNameFromFactory( pSubMenu->GetItemCommand( nId ) );
            SfxObjectFactory::SetStandardTemplate( aServiceName, String() );
            bHandled = sal_True;
        }
    }

    return bHandled ? 1 : 0;
}

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

IMPL_LINK_INLINE_START( SfxOrganizeDlg_Impl, MenuSelect_Impl, Menu *, pMenu )

/*  [Beschreibung]

    SelectHandler des Men"us des Men"ubuttons (SV)

    [Parameter]

    MenuButton *pBtn                der das Event ausl"osende Button

    [R"uckgabewert]                 1: Event wurde verarbeitet,
                                    0: Event wurde nicht verarbeitet (SV-Menu)

*/
{
    return Dispatch_Impl( pMenu->GetCurItemId(), pMenu );
}
IMPL_LINK_INLINE_END( SfxOrganizeDlg_Impl, MenuSelect_Impl, Menu *, pMenu )

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

IMPL_LINK( SfxOrganizeDlg_Impl, AccelSelect_Impl, Accelerator *, pAccel )

/*  [Beschreibung]

    SelectHandler des Accelerators (SV)

    [Parameter]

    Accelerator *pAccel             der das Event ausl"osende Accelerator

    [R"uckgabewert]                 1: Event wurde verarbeitet,
                                    0: Event wurde nicht verarbeitet (SV)

*/

{
    SvLBoxEntry* pEntry = pFocusBox && pFocusBox->GetSelectionCount() ?
        pFocusBox->FirstSelected() : NULL ;
    return pEntry && ( pAccel->GetCurItemId() == ID_NEW  || !DontDelete_Impl( pEntry ) ) ?
        Dispatch_Impl( pAccel->GetCurItemId(), NULL ) : 0;
}

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

void SfxOrganizeDlg_Impl::OkHdl(Button *pButton)
{
    if(pFocusBox && pFocusBox->IsEditingActive())
        pFocusBox->EndEditing(FALSE);
    pButton->Click();
}



IMPL_LINK( SfxOrganizeDlg_Impl, MenuActivate_Impl, Menu *, pMenu )

/*  [Beschreibung]

    ActivateHandler des Men"us des Men"ubuttons (SV)

    [Parameter]

    Menu *pMenu                     das das Event ausl"osende Men"u

    [R"uckgabewert]                 1: Event wurde verarbeitet,
                                    0: Event wurde nicht verarbeitet (SV-Menu)

*/
{
    if ( pFocusBox && pFocusBox->IsEditingActive() )
        pFocusBox->EndEditing( FALSE );
    BOOL bEnable = ( pFocusBox && pFocusBox->GetSelectionCount() );
    SvLBoxEntry* pEntry = bEnable ? pFocusBox->FirstSelected() : NULL;
    const USHORT nDepth =
        ( bEnable && pFocusBox->GetSelectionCount() ) ? pFocusBox->GetModel()->GetDepth( pEntry ) : 0;
    const USHORT nDocLevel = bEnable ? pFocusBox->GetDocLevel() : 0;
    int eVT = pFocusBox ? pFocusBox->GetViewType() : 0;
        // nur Vorlagen anlegen
    pMenu->EnableItem( ID_NEW, bEnable && 0 == nDepth && SfxOrganizeListBox_Impl::VIEW_TEMPLATES == eVT );
    // Vorlagen: Loeschen Ebene 0,1,3ff
    //           ein Bereich mu"s mindestens erhalten bleiben
    // Dateien : Loeschen Ebene > 2

    pMenu->EnableItem( ID_DELETE, bEnable && !DontDelete_Impl( pEntry ) );
    pMenu->EnableItem( ID_EDIT,
                       bEnable && eVT == SfxOrganizeListBox_Impl::VIEW_TEMPLATES && nDepth == nDocLevel
                           && !DontDelete_Impl( pEntry ) );
    pMenu->EnableItem( ID_COPY_FROM,
                       bEnable && eVT == SfxOrganizeListBox_Impl::VIEW_TEMPLATES &&
                       ( nDepth == nDocLevel || nDepth == nDocLevel - 1 ) );
    pMenu->EnableItem( ID_COPY_TO,
                       bEnable && eVT == SfxOrganizeListBox_Impl::VIEW_TEMPLATES &&
                       nDepth == nDocLevel );
    pMenu->EnableItem( ID_RESCAN,
                       SfxOrganizeListBox_Impl::VIEW_TEMPLATES == aRightLb.GetViewType() ||
                       SfxOrganizeListBox_Impl::VIEW_TEMPLATES == aLeftLb.GetViewType() );
    BOOL bPrint = bEnable && nDepth > pFocusBox->GetDocLevel();
    if ( bPrint && pPrt )
        bPrint = !pPrt->IsPrinting() && !pPrt->IsJobActive();
    if ( bPrint && bEnable )
    {
        // only styles printable
        Path aPath( pFocusBox, pFocusBox->FirstSelected() );
        USHORT nIndex = aPath[ nDocLevel + 1 ];
        bPrint = ( nIndex == CONTENT_STYLE );
                }
    pMenu->EnableItem( ID_PRINT, bPrint );

    if ( bEnable && eVT == SfxOrganizeListBox_Impl::VIEW_TEMPLATES && nDepth == nDocLevel )
    {
        String aFactoryURL, aFileURL;
        bEnable = GetServiceName_Impl( aFactoryURL, aFileURL );
    }
    else if ( bEnable )
        bEnable = FALSE;
    pMenu->EnableItem( ID_DEFAULT_TEMPLATE, bEnable );

    bEnable = sal_True;
    SvStringsDtor* pList = GetAllFactoryURLs_Impl();
    USHORT nCount = pList->Count();
    if ( nCount > 0 )
    {
        PopupMenu* pSubMenu = new PopupMenu;
        USHORT nItemId = ID_RESET_DEFAULT_TEMPLATE + 1;
        for ( USHORT i = 0; i < nCount; ++i )
        {
            String aObjFacURL( *pList->GetObject(i) );
            String aTitle = SvFileInformationManager::GetDescription(
                INetURLObject(aObjFacURL) );
            pSubMenu->InsertItem( nItemId, aTitle,
                SvFileInformationManager::GetImage(INetURLObject(aObjFacURL)) );
            pSubMenu->SetItemCommand( nItemId++, aObjFacURL );
            DBG_ASSERT( nItemId <= ID_RESET_DEFAULT_TEMPLATE_END, "menu item id overflow" );
        }
        pMenu->SetPopupMenu( ID_RESET_DEFAULT_TEMPLATE, pSubMenu );
    }
    else
        bEnable = sal_False;

    delete pList;
    pMenu->EnableItem( ID_RESET_DEFAULT_TEMPLATE, bEnable );

    return 1;
}

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

IMPL_LINK( SfxOrganizeDlg_Impl, GetFocus_Impl, SfxOrganizeListBox_Impl *, pBox )

/*  [Beschreibung]

    GetFocus-Handler, wird aus den Select-Handler der Listboxen
    gerufen.
    Wird verwendet, im die Listbox, die den Focus besitzt sowie
    deren Zustand zu ermitteln.

    [Parameter]

    SfxOrganizeListBox *pBox        die rufende Box

*/

{
    if(pFocusBox && pFocusBox != pBox)
        pFocusBox->SelectAll(FALSE);
    pFocusBox = pBox;
    aFilesBtn.Enable( SfxOrganizeListBox_Impl::VIEW_FILES ==
                      pFocusBox->GetViewType() );
    return 0;
}

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

IMPL_LINK( SfxOrganizeDlg_Impl, LeftListBoxSelect_Impl, ListBox *, pBox )

/*  [Beschreibung]

    Select-Handler, wird aus den Select-Handler der Listboxen
    gerufen.
    Wenn sich der Modus der Boxen (Dokumentsicht, Dokumentvorlagensicht)
    unterscheiden, werden die Models getrennt; andernfalls zusammengefa"st.

    [Parameter]

    ListBox *pBox               die rufende Box

*/
{
    const SfxOrganizeListBox_Impl::DataEnum
        eViewType = pBox->GetSelectEntryPos() == 0 ?
        SfxOrganizeListBox_Impl::VIEW_TEMPLATES : SfxOrganizeListBox_Impl::VIEW_FILES;
    if(eViewType!= aLeftLb.GetViewType()) {
        aLeftLb.SetViewType(eViewType);
        if(aRightLb.GetViewType() == eViewType)
            aLeftLb.SetModel(aRightLb.GetModel());
        else {
            // Models trennen
            aLeftLb.DisconnectFromModel();
            aLeftLb.Reset();
        }
    }
    GetFocus_Impl(&aLeftLb);
    return 0;
}

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

IMPL_LINK( SfxOrganizeDlg_Impl, RightListBoxSelect_Impl, ListBox *, pBox )

/*  [Beschreibung]

    Select-Handler, wird aus den Select-Handler der Listboxen
    gerufen.
    Wenn sich der Modus der Boxen (Dokumentsicht, Dokumentvorlagensicht)
    unterscheiden, werden die Models getrennt; andernfalls zusammengefa"st.

    [Parameter]

    ListBox *pBox               die rufende Box

*/
{
    const SfxOrganizeListBox_Impl::DataEnum eViewType =
        pBox->GetSelectEntryPos() == 0 ?
        SfxOrganizeListBox_Impl::VIEW_TEMPLATES : SfxOrganizeListBox_Impl::VIEW_FILES;
    if(eViewType!= aRightLb.GetViewType())
    {
        aRightLb.SetViewType(eViewType);
        if(aLeftLb.GetViewType() == eViewType)
            aRightLb.SetModel(aLeftLb.GetModel());
        else
        {
            // Models trennen
            aRightLb.DisconnectFromModel();
            aRightLb.Reset();
        }
    }
    aRightLb.GrabFocus();
    GetFocus_Impl(&aRightLb);
    return 0;
}

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

IMPL_LINK( SfxOrganizeDlg_Impl, OnAddressTemplateClicked, Button *, pButton )
{
    (void)pButton; //unused
    svt::AddressBookSourceDialog aDialog(pDialog, ::comphelper::getProcessServiceFactory());
    aDialog.Execute();
    return 0L;
}

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

IMPL_LINK( SfxOrganizeDlg_Impl, AddFiles_Impl, Button *, pButton )

/*  [Beschreibung]

    Handler des Buttons f"ur das Hinzuf"ugen von Dateien per Dialog.

    [Parameter]

    Button *                der Button, der dieses Events ausgel"ost hat.

*/
{
    (void)pButton; //unused
    if ( pFileDlg )
        delete pFileDlg;
    pFileDlg = new sfx2::FileDialogHelper( WB_OPEN, String() );

    // add config and basic filter
    static String sOpenBracket( DEFINE_CONST_UNICODE( " (" ) );
    static String sCloseBracket( DEFINE_CONST_UNICODE( ")" ) );
    static String sConfigExt( DEFINE_CONST_UNICODE( "*.cfg" ) );
    static String sBasicExt( DEFINE_CONST_UNICODE( "*.sbl" ) );

    String sFilterName( SfxResId( RID_STR_FILTCONFIG ) );
    sFilterName += sOpenBracket;
    sFilterName += sConfigExt;
    sFilterName += sCloseBracket;
    pFileDlg->AddFilter( sFilterName, sConfigExt );

    sFilterName = String( SfxResId( RID_STR_FILTBASIC ) );
    sFilterName += sOpenBracket;
    sFilterName += sBasicExt;
    sFilterName += sCloseBracket;
    pFileDlg->AddFilter( sFilterName, sBasicExt );

    // set "All" filter as current
    pFileDlg->SetCurrentFilter( String( SfxResId( STR_SFX_FILTERNAME_ALL ) ) );

    if ( aLastDir.Len() )
        pFileDlg->SetDisplayDirectory( aLastDir );

    pFileDlg->StartExecuteModal( LINK( this, SfxOrganizeDlg_Impl, AddFilesHdl ) );

    return 0;
}

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

IMPL_LINK( SfxOrganizeDlg_Impl, ImportHdl, sfx2::FileDialogHelper *, EMPTYARG )
{
    DBG_ASSERT( pFileDlg, "SfxOrganizeDlg_Impl::ImportHdl(): no file dialog" );

    if ( ERRCODE_NONE == pFileDlg->GetError() )
    {
        String aPath = pFileDlg->GetPath();
        INetURLObject aObj( aPath );

        // we want to keep the original extension when exporting, the file open dialog
        // always sets the extension to *.vor
        if ( pFileDlg->GetDialogType() ==
                com::sun::star::ui::dialogs::TemplateDescription::FILESAVE_SIMPLE )
        {
            if ( aObj.hasExtension() )
                aObj.removeExtension();

            aObj.setExtension( m_sExtension4Save );
            aPath = aObj.GetMainURL( INetURLObject::DECODE_TO_IURI );
        }

        aObj.removeSegment();
        aLastDir = aObj.GetMainURL( INetURLObject::DECODE_TO_IURI );

        if ( aPath.Len() && !aMgr.CopyTo( m_nRegion, m_nIndex, aPath ) )
        {
            String aText( SfxResId( STR_ERROR_COPY_TEMPLATE ) );
            aText.SearchAndReplaceAscii( "$1", aPath );
            ErrorBox( pDialog, WB_OK, aText ).Execute();
        }
    }

    return 0L;
}

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

IMPL_LINK( SfxOrganizeDlg_Impl, ExportHdl, sfx2::FileDialogHelper *, EMPTYARG )
{
    DBG_ASSERT( pFileDlg, "SfxOrganizeDlg_Impl::ImportHdl(): no file dialog" );
    ::com::sun::star::uno::Sequence< ::rtl::OUString > aPaths;

    if ( ERRCODE_NONE == pFileDlg->GetError() )
    {
        aPaths = pFileDlg->GetMPath();
        sal_Int32 lastCount = aPaths.getLength() - 1;
        INetURLObject aObj( aPaths.getArray()[ lastCount ] );

        aObj.removeSegment();
        aLastDir = aObj.GetMainURL( INetURLObject::DECODE_TO_IURI );
    }

    sal_Int32 nCount = aPaths.getLength();
    if ( 1 == nCount )
    {
       String aPath = String( aPaths.getArray()[0] );
       if ( aPath.Len() && !aMgr.CopyFrom( pFocusBox, m_nRegion, m_nIndex, aPath ) )
       {
           String aText( SfxResId( STR_ERROR_COPY_TEMPLATE ) );
           aText.SearchAndReplaceAscii( "$1", aPath );
           ErrorBox( pDialog, WB_OK, aText ).Execute();
       }
    }
    else if ( nCount > 1 )
    {
        INetURLObject aPathObj( aPaths[0] );
        aPathObj.setFinalSlash();
        for ( USHORT i = 1; i < nCount; ++i )
        {
            if ( 1 == i )
                aPathObj.Append( aPaths[i] );
            else
                aPathObj.setName( aPaths[i] );
            String aPath = aPathObj.GetMainURL( INetURLObject::NO_DECODE );
            if ( aPath.Len() && !aMgr.CopyFrom( pFocusBox, m_nRegion, m_nIndex, aPath ) )
            {
                String aText( SfxResId( STR_ERROR_COPY_TEMPLATE ) );
                aText.SearchAndReplaceAscii( "$1", aPath );
                ErrorBox( pDialog, WB_OK, aText ).Execute();
            }
        }
    }

    return 0L;
}

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

IMPL_LINK( SfxOrganizeDlg_Impl, AddFilesHdl, sfx2::FileDialogHelper *, EMPTYARG )
{
    if ( ERRCODE_NONE == pFileDlg->GetError() )
    {
        String aPath = pFileDlg->GetPath();
        aMgr.InsertFile( pFocusBox, aPath );
        INetURLObject aObj( aPath );
        aObj.removeSegment();
        aObj.setFinalSlash();
        aLastDir = aObj.GetMainURL( INetURLObject::DECODE_TO_IURI );
    }

    return 0L;
}

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

short SfxTemplateOrganizeDlg::Execute()

/*  [Beschreibung]

    "Uberladene Execute- Methode; speichert gfs. "Anderungen an den
    Dokumentvorlagen
    (SV-Methode)

*/

{
    const short nRet = ModalDialog::Execute();
    if(RET_CANCEL != nRet)
    {
        pImp->aMgr.SaveAll(this);
        SfxTemplateDialog* pTemplDlg = SFX_APP()->GetTemplateDialog();
        if(pTemplDlg)
            pTemplDlg->Update();
    }
    return nRet;
}


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

SfxTemplateOrganizeDlg::SfxTemplateOrganizeDlg(Window * pParent,
                                                SfxDocumentTemplates *pTempl)
:   ModalDialog( pParent, SfxResId(DLG_ORGANIZE)),
    pImp( new SfxOrganizeDlg_Impl(this, pTempl) )

/*  [Beschreibung]

    Konstruktor

*/
{
    FreeResource();
}

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

SfxTemplateOrganizeDlg::~SfxTemplateOrganizeDlg()
{
    GetpApp()->RemoveAccel(&pImp->aEditAcc);
    delete pImp->pPrt;
    delete pImp;
}

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