/*************************************************************************
 *
 * 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_svx.hxx"
#include <svx/dialmgr.hxx>

#include <svx/dialogs.hrc>
#include "docrecovery.hxx"
#include "docrecovery.hrc"

#include <comphelper/processfactory.hxx>
#include <comphelper/sequenceashashmap.hxx>
#include <comphelper/configurationhelper.hxx>
#include <svtools/imagemgr.hxx>
#include <svtools/xtextedt.hxx>
#include <tools/urlobj.hxx>
#include <vcl/msgbox.hxx>
#include <vcl/svapp.hxx>
#include <rtl/ustrbuf.hxx>
#include <vcl/scrbar.hxx>

#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
#include <toolkit/unohlp.hxx>
#endif

//#include "com/sun/star/lang/XMultiServiceFactory.hpp"
#include <com/sun/star/task/XStatusIndicatorFactory.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
//#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/util/URL.hpp>
#include <com/sun/star/util/XURLTransformer.hpp>
#include <com/sun/star/frame/XDispatch.hpp>
#include <com/sun/star/awt/XWindow.hpp>
#include <com/sun/star/ui/dialogs/XFolderPicker.hpp>
#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
#include <osl/file.hxx>
#include <osl/security.hxx>
#include <rtl/bootstrap.hxx>
#include <unotools/pathoptions.hxx>
#include <unotools/localfilehelper.hxx>

#define RET_BACK    100

//===============================================
// namespace
namespace svx{
    namespace DocRecovery{

namespace css = ::com::sun::star;

using namespace ::rtl;
using namespace ::osl;

//===============================================
TabDialog4Recovery::TabDialog4Recovery(Window* pParent)
    : TabDialog    (pParent, SVX_RES( RID_SVX_TABDLG_DOCRECOVERY ))
    , m_pActualPage(m_lTabPages.begin()                           )
{
}

//===============================================
TabDialog4Recovery::~TabDialog4Recovery()
{
    m_lTabPages.clear();
}

//===============================================
void TabDialog4Recovery::addTabPage(IExtendedTabPage* pPage)
{
    if (pPage)
        m_lTabPages.push_back(pPage);
}

//===============================================
short TabDialog4Recovery::Execute()
{
    ::vos::OGuard aLock(Application::GetSolarMutex());

    Show();
    m_pActualPage = m_lTabPages.begin();
    while(sal_True)
    {
        IExtendedTabPage* pPage = *m_pActualPage;
        SetViewWindow(pPage);
        pPage->Show();
        pPage->setDefButton();
        short nRet = pPage->execute();
        pPage->Hide();

        switch(nRet)
        {
            case DLG_RET_OK :
                {
                    ++m_pActualPage;
                    if (m_pActualPage == m_lTabPages.end())
                        return nRet;
                }
                break;

            case DLG_RET_BACK :
                {
                    if (m_pActualPage != m_lTabPages.begin())
                        --m_pActualPage;
                }
                break;

            case DLG_RET_UNKNOWN :
            case DLG_RET_CANCEL :
            case DLG_RET_OK_AUTOLUNCH :
                return nRet;
        }
    }
}

//===============================================
RecoveryCore::RecoveryCore(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR         ,
                                 sal_Bool                                                bUsedForSaving)
    : m_xSMGR           ( xSMGR        )
    , m_pListener       ( 0            )
    , m_bListenForSaving(bUsedForSaving)
{
    impl_startListening();
}

//===============================================
RecoveryCore::~RecoveryCore()
{
    impl_stopListening();
}

//===============================================
css::uno::Reference< css::lang::XMultiServiceFactory > RecoveryCore::getSMGR()
{
    return m_xSMGR;
}

//===============================================
TURLList* RecoveryCore::getURLListAccess()
{
    return &m_lURLs;
}

//===============================================
sal_Bool RecoveryCore::existsBrokenTempEntries()
{
    TURLList::const_iterator pIt;
    for (  pIt  = m_lURLs.begin();
           pIt != m_lURLs.end()  ;
         ++pIt                   )
    {
        const TURLInfo& rInfo = *pIt;
        if (RecoveryCore::isBrokenTempEntry(rInfo))
            return sal_True;
    }

    return sal_False;
}

//===============================================
sal_Bool RecoveryCore::existsNonRecoveredEntries()
{
    TURLList::const_iterator pIt;
    for (  pIt  = m_lURLs.begin();
           pIt != m_lURLs.end()  ;
         ++pIt                   )
    {
        const TURLInfo& rInfo = *pIt;
        if (rInfo.RecoveryState == E_NOT_RECOVERED_YET)
            return sal_True;
    }

    return sal_False;
}

//===============================================
sal_Bool RecoveryCore::isBrokenTempEntry(const TURLInfo& rInfo)
{
    if (!rInfo.TempURL.getLength())
        return sal_False;

    // Note: If the original files was recovery ... but a temp file
    // exists ... an error inside the temp file exists!
    if (
        !(rInfo.RecoveryState == E_RECOVERY_FAILED            ) &&
        !(rInfo.RecoveryState == E_ORIGINAL_DOCUMENT_RECOVERED)
       )
       return sal_False;

    return sal_True;
}

//===============================================
void RecoveryCore::saveBrokenTempEntries(const ::rtl::OUString& sPath)
{
    if (!sPath.getLength())
        return;

    if (!m_xRealCore.is())
        return;

    // prepare all needed parameters for the following dispatch() request.
    css::util::URL aCopyURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_BACKUP);
    css::uno::Sequence< css::beans::PropertyValue > lCopyArgs(3);
    lCopyArgs[0].Name    = PROP_DISPATCHASYNCHRON;
    lCopyArgs[0].Value <<= sal_False;
    lCopyArgs[1].Name    = PROP_SAVEPATH;
    lCopyArgs[1].Value <<= sPath;
    lCopyArgs[2].Name    = PROP_ENTRYID;
    // lCopyArgs[2].Value will be changed during next loop ...

    // work on a copied list only ...
    // Reason: We will get notifications from the core for every
    // changed or removed element. And that will change our m_lURLs list.
    // That's not a good idea, if we use a stl iterator inbetween .-)
    TURLList lURLs = m_lURLs;
    TURLList::const_iterator pIt;
    for (  pIt  = lURLs.begin();
           pIt != lURLs.end()  ;
         ++pIt                 )
    {
        const TURLInfo& rInfo = *pIt;
        if (!RecoveryCore::isBrokenTempEntry(rInfo))
            continue;

        lCopyArgs[2].Value <<= rInfo.ID;
        m_xRealCore->dispatch(aCopyURL, lCopyArgs);
    }
}

//===============================================
void RecoveryCore::saveAllTempEntries(const ::rtl::OUString& sPath)
{
    if (!sPath.getLength())
        return;

    if (!m_xRealCore.is())
        return;

    // prepare all needed parameters for the following dispatch() request.
    css::util::URL aCopyURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_BACKUP);
    css::uno::Sequence< css::beans::PropertyValue > lCopyArgs(3);
    lCopyArgs[0].Name    = PROP_DISPATCHASYNCHRON;
    lCopyArgs[0].Value <<= sal_False;
    lCopyArgs[1].Name    = PROP_SAVEPATH;
    lCopyArgs[1].Value <<= sPath;
    lCopyArgs[2].Name    = PROP_ENTRYID;
    // lCopyArgs[2].Value will be changed during next loop ...

    // work on a copied list only ...
    // Reason: We will get notifications from the core for every
    // changed or removed element. And that will change our m_lURLs list.
    // That's not a good idea, if we use a stl iterator inbetween .-)
    TURLList lURLs = m_lURLs;
    TURLList::const_iterator pIt;
    for (  pIt  = lURLs.begin();
           pIt != lURLs.end()  ;
         ++pIt                 )
    {
        const TURLInfo& rInfo = *pIt;
        if (!rInfo.TempURL.getLength())
            continue;

        lCopyArgs[2].Value <<= rInfo.ID;
        m_xRealCore->dispatch(aCopyURL, lCopyArgs);
    }
}

//===============================================
void RecoveryCore::forgetBrokenTempEntries()
{
    if (!m_xRealCore.is())
        return;

    css::util::URL aRemoveURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_CLEANUP);
    css::uno::Sequence< css::beans::PropertyValue > lRemoveArgs(2);
    lRemoveArgs[0].Name    = PROP_DISPATCHASYNCHRON;
    lRemoveArgs[0].Value <<= sal_False;
    lRemoveArgs[1].Name    = PROP_ENTRYID;
    // lRemoveArgs[1].Value will be changed during next loop ...

    // work on a copied list only ...
    // Reason: We will get notifications from the core for every
    // changed or removed element. And that will change our m_lURLs list.
    // That's not a good idea, if we use a stl iterator inbetween .-)
    TURLList lURLs = m_lURLs;
    TURLList::const_iterator pIt;
    for (  pIt  = lURLs.begin();
           pIt != lURLs.end()  ;
         ++pIt                 )
    {
        const TURLInfo& rInfo = *pIt;
        if (!RecoveryCore::isBrokenTempEntry(rInfo))
            continue;

        lRemoveArgs[1].Value <<= rInfo.ID;
        m_xRealCore->dispatch(aRemoveURL, lRemoveArgs);
    }
}

//===============================================
void RecoveryCore::forgetAllRecoveryEntries()
{
    if (!m_xRealCore.is())
        return;

    css::util::URL aRemoveURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_CLEANUP);
    css::uno::Sequence< css::beans::PropertyValue > lRemoveArgs(2);
    lRemoveArgs[0].Name    = PROP_DISPATCHASYNCHRON;
    lRemoveArgs[0].Value <<= sal_False;
    lRemoveArgs[1].Name    = PROP_ENTRYID;
    // lRemoveArgs[1].Value will be changed during next loop ...

    // work on a copied list only ...
    // Reason: We will get notifications from the core for every
    // changed or removed element. And that will change our m_lURLs list.
    // That's not a good idea, if we use a stl iterator inbetween .-)
    TURLList lURLs = m_lURLs;
    TURLList::const_iterator pIt;
    for (  pIt  = lURLs.begin();
           pIt != lURLs.end()  ;
         ++pIt                 )
    {
        const TURLInfo& rInfo = *pIt;
        lRemoveArgs[1].Value <<= rInfo.ID;
        m_xRealCore->dispatch(aRemoveURL, lRemoveArgs);
    }
}

//===============================================
void RecoveryCore::forgetBrokenRecoveryEntries()
{
    if (!m_xRealCore.is())
        return;

    css::util::URL aRemoveURL = impl_getParsedURL(RECOVERY_CMD_DO_ENTRY_CLEANUP);
    css::uno::Sequence< css::beans::PropertyValue > lRemoveArgs(2);
    lRemoveArgs[0].Name    = PROP_DISPATCHASYNCHRON;
    lRemoveArgs[0].Value <<= sal_False;
    lRemoveArgs[1].Name    = PROP_ENTRYID;
    // lRemoveArgs[1].Value will be changed during next loop ...

    // work on a copied list only ...
    // Reason: We will get notifications from the core for every
    // changed or removed element. And that will change our m_lURLs list.
    // That's not a good idea, if we use a stl iterator inbetween .-)
    TURLList lURLs = m_lURLs;
    TURLList::const_iterator pIt;
    for (  pIt  = lURLs.begin();
           pIt != lURLs.end()  ;
         ++pIt                 )
    {
        const TURLInfo& rInfo = *pIt;
        if (!RecoveryCore::isBrokenTempEntry(rInfo))
            continue;

        lRemoveArgs[1].Value <<= rInfo.ID;
        m_xRealCore->dispatch(aRemoveURL, lRemoveArgs);
    }
}

//===============================================
void RecoveryCore::setProgressHandler(const css::uno::Reference< css::task::XStatusIndicator >& xProgress)
{
    m_xProgress = xProgress;
}

//===============================================
void RecoveryCore::setUpdateListener(IRecoveryUpdateListener* pListener)
{
    m_pListener = pListener;
}

//===============================================
void RecoveryCore::doEmergencySavePrepare()
{
    if (!m_xRealCore.is())
        return;

    css::util::URL aURL = impl_getParsedURL(RECOVERY_CMD_DO_PREPARE_EMERGENCY_SAVE);

    css::uno::Sequence< css::beans::PropertyValue > lArgs(1);
    lArgs[0].Name    = PROP_DISPATCHASYNCHRON;
    lArgs[0].Value <<= sal_False;

    m_xRealCore->dispatch(aURL, lArgs);
}

//===============================================
void RecoveryCore::doEmergencySave()
{
    if (!m_xRealCore.is())
        return;

    css::util::URL aURL = impl_getParsedURL(RECOVERY_CMD_DO_EMERGENCY_SAVE);

    css::uno::Sequence< css::beans::PropertyValue > lArgs(2);
    lArgs[0].Name    = PROP_STATUSINDICATOR;
    lArgs[0].Value <<= m_xProgress;
    lArgs[1].Name    = PROP_DISPATCHASYNCHRON;
    lArgs[1].Value <<= sal_True;

    m_xRealCore->dispatch(aURL, lArgs);
}

//===============================================
void RecoveryCore::doRecovery()
{
    if (!m_xRealCore.is())
        return;

    css::util::URL aURL = impl_getParsedURL(RECOVERY_CMD_DO_RECOVERY);

    css::uno::Sequence< css::beans::PropertyValue > lArgs(2);
    lArgs[0].Name    = PROP_STATUSINDICATOR;
    lArgs[0].Value <<= m_xProgress;
    lArgs[1].Name    = PROP_DISPATCHASYNCHRON;
    lArgs[1].Value <<= sal_True;

    m_xRealCore->dispatch(aURL, lArgs);
}

//===============================================
ERecoveryState RecoveryCore::mapDocState2RecoverState(sal_Int32 eDocState)
{
    // ???
    ERecoveryState eRecState = E_NOT_RECOVERED_YET;

    /* Attention:
        Some of the following states can occure at the
        same time. So we have to check for the "worst case" first!

        DAMAGED -> INCOMPLETE -> HANDLED
     */

    // running ...
    if (
        ((eDocState & E_TRY_LOAD_BACKUP  ) == E_TRY_LOAD_BACKUP  ) ||
        ((eDocState & E_TRY_LOAD_ORIGINAL) == E_TRY_LOAD_ORIGINAL)
       )
        eRecState = E_RECOVERY_IS_IN_PROGRESS;
    // red
    else
    if ((eDocState & E_DAMAGED) == E_DAMAGED)
        eRecState = E_RECOVERY_FAILED;
    // yellow
    else
    if ((eDocState & E_INCOMPLETE) == E_INCOMPLETE)
        eRecState = E_ORIGINAL_DOCUMENT_RECOVERED;
    // green
    else
    if ((eDocState & E_SUCCEDED) == E_SUCCEDED)
        eRecState = E_SUCCESSFULLY_RECOVERED;

    return eRecState;
}

//===============================================
void SAL_CALL RecoveryCore::statusChanged(const css::frame::FeatureStateEvent& aEvent)
    throw(css::uno::RuntimeException)
{
    // a) special notification about start/stop async dispatch!
    //    FeatureDescriptor = "start" || "stop"
    if (aEvent.FeatureDescriptor.equals(RECOVERY_OPERATIONSTATE_START))
    {
        if (m_pListener)
            m_pListener->start();
        return;
    }

    if (aEvent.FeatureDescriptor.equals(RECOVERY_OPERATIONSTATE_STOP))
    {
        if (m_pListener)
            m_pListener->end();
        return;
    }

    // b) normal notification about changed items
    //    FeatureDescriptor = "Update"
    //    State             = Lits of informations [seq< NamedValue >]
    if (! aEvent.FeatureDescriptor.equals(RECOVERY_OPERATIONSTATE_UPDATE))
        return;

    ::comphelper::SequenceAsHashMap lInfo(aEvent.State);
    TURLInfo                        aNew;

    aNew.ID          = lInfo.getUnpackedValueOrDefault(STATEPROP_ID         , (sal_Int32)0     );
    aNew.DocState    = lInfo.getUnpackedValueOrDefault(STATEPROP_STATE      , (sal_Int32)0     );
    aNew.OrgURL      = lInfo.getUnpackedValueOrDefault(STATEPROP_ORGURL     , ::rtl::OUString());
    aNew.TempURL     = lInfo.getUnpackedValueOrDefault(STATEPROP_TEMPURL    , ::rtl::OUString());
    aNew.FactoryURL  = lInfo.getUnpackedValueOrDefault(STATEPROP_FACTORYURL , ::rtl::OUString());
    aNew.TemplateURL = lInfo.getUnpackedValueOrDefault(STATEPROP_TEMPLATEURL, ::rtl::OUString());
    aNew.DisplayName = lInfo.getUnpackedValueOrDefault(STATEPROP_TITLE      , ::rtl::OUString());
    aNew.Module      = lInfo.getUnpackedValueOrDefault(STATEPROP_MODULE     , ::rtl::OUString());

    // search for already existing items and update her nState value ...
    TURLList::iterator pIt;
    for (  pIt  = m_lURLs.begin();
           pIt != m_lURLs.end()  ;
         ++pIt                   )
    {
        TURLInfo& aOld = *pIt;
        if (aOld.ID == aNew.ID)
        {
            // change existing
            aOld.DocState      = aNew.DocState;
            aOld.RecoveryState = RecoveryCore::mapDocState2RecoverState(aOld.DocState);
            if (m_pListener)
            {
                m_pListener->updateItems();
                m_pListener->stepNext(&aOld);
            }
            return;
        }
    }

    // append as new one
    // TODO think about mmatching Module name to a corresponding icon
    String sURL = aNew.OrgURL;
    if (!sURL.Len())
        sURL = aNew.FactoryURL;
    if (!sURL.Len())
        sURL = aNew.TempURL;
    if (!sURL.Len())
        sURL = aNew.TemplateURL;
    INetURLObject aURL(sURL);
    aNew.StandardImage = SvFileInformationManager::GetFileImage(aURL, false, false);
    aNew.HCImage       = SvFileInformationManager::GetFileImage(aURL, false, true );

    /* set the right UI state for this item to NOT_RECOVERED_YET ... because nDocState shows the state of
       the last emergency save operation before and is interessting for the used recovery core service only ...
       for now! But if there is a further notification for this item (see lines above!) we must
       map the doc state to an UI state. */
    aNew.RecoveryState = E_NOT_RECOVERED_YET;

    // patch DisplayName! Because the document title contain more then the file name ...
    sal_Int32 i = aNew.DisplayName.indexOf(::rtl::OUString::createFromAscii(" - "));
    if (i > 0)
        aNew.DisplayName = aNew.DisplayName.copy(0, i);

    m_lURLs.push_back(aNew);

    if (m_pListener)
        m_pListener->updateItems();
}

//===============================================
void SAL_CALL RecoveryCore::disposing(const css::lang::EventObject& /*aEvent*/)
    throw(css::uno::RuntimeException)
{
    m_xRealCore.clear();
}

//===============================================
void RecoveryCore::impl_startListening()
{
    // listening already initialized ?
    if (m_xRealCore.is())
        return;
    m_xRealCore = css::uno::Reference< css::frame::XDispatch >(m_xSMGR->createInstance(SERVICENAME_RECOVERYCORE), css::uno::UNO_QUERY_THROW);

    css::util::URL aURL;
    if (m_bListenForSaving)
        aURL.Complete = RECOVERY_CMD_DO_EMERGENCY_SAVE;
    else
        aURL.Complete = RECOVERY_CMD_DO_RECOVERY;
    css::uno::Reference< css::util::XURLTransformer > xParser(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY_THROW);
    xParser->parseStrict(aURL);

    /* Note: addStatusListener() call us synchronous back ... so we
             will get the complete list of currently open documents! */
    m_xRealCore->addStatusListener(static_cast< css::frame::XStatusListener* >(this), aURL);
}

//===============================================
void RecoveryCore::impl_stopListening()
{
    // Ignore it, if this instance doesnt listen currently
    if (!m_xRealCore.is())
        return;

    css::util::URL aURL;
    if (m_bListenForSaving)
        aURL.Complete = RECOVERY_CMD_DO_EMERGENCY_SAVE;
    else
        aURL.Complete = RECOVERY_CMD_DO_RECOVERY;
    css::uno::Reference< css::util::XURLTransformer > xParser(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY_THROW);
    xParser->parseStrict(aURL);

    m_xRealCore->removeStatusListener(static_cast< css::frame::XStatusListener* >(this), aURL);
    m_xRealCore.clear();
}

//===============================================
css::util::URL RecoveryCore::impl_getParsedURL(const ::rtl::OUString& sURL)
{
    css::util::URL aURL;
    aURL.Complete = sURL;

    css::uno::Reference< css::util::XURLTransformer > xParser(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), css::uno::UNO_QUERY_THROW);
    xParser->parseStrict(aURL);

    return aURL;
}

//===============================================
PluginProgressWindow::PluginProgressWindow(      Window*                                       pParent  ,
                                           const css::uno::Reference< css::lang::XComponent >& xProgress)
    : Window     (pParent  )
    , m_xProgress(xProgress)
{
    Show();
    Size aParentSize = pParent->GetSizePixel();
    // align the progressbar to its parent
    SetPosSizePixel( -9, 0, aParentSize.Width() + 15, aParentSize.Height() - 4 );
}

//===============================================
PluginProgressWindow::~PluginProgressWindow()
{
    if (m_xProgress.is())
        m_xProgress->dispose();
}

//===============================================
PluginProgress::PluginProgress(      Window*                                                 pParent,
                               const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR  )
{
    m_pPlugProgressWindow = new PluginProgressWindow(pParent, static_cast< css::lang::XComponent* >(this));
    css::uno::Reference< css::awt::XWindow > xProgressWindow = VCLUnoHelper::GetInterface(m_pPlugProgressWindow);
    m_xProgressFactory = css::uno::Reference< css::task::XStatusIndicatorFactory >(xSMGR->createInstance(SERVICENAME_PROGRESSFACTORY), css::uno::UNO_QUERY_THROW);
    css::uno::Reference< css::lang::XInitialization > xInit(m_xProgressFactory, css::uno::UNO_QUERY_THROW);

    css::uno::Sequence< css::uno::Any > lArgs(2);
    css::beans::NamedValue aProp;
    aProp.Name    = PROP_PARENTWINDOW;
    aProp.Value <<= xProgressWindow;
    lArgs[0]    <<= aProp;
    aProp.Name    = PROP_ALLOWPARENTSHOW;
    aProp.Value <<= sal_True;
    lArgs[1]    <<= aProp;

    xInit->initialize(lArgs);

    m_xProgress = m_xProgressFactory->createStatusIndicator();
}

//===============================================
PluginProgress::~PluginProgress()
{
}

//===============================================
Window* PluginProgress::getPlugWindow()
{
    return m_pPlugProgressWindow;
}

//===============================================
void SAL_CALL PluginProgress::dispose()
    throw(css::uno::RuntimeException)
{
    // m_pPluginProgressWindow was deleted ...
    // So the internal pointer of this progress
    // weill be dead!
    m_xProgress.clear();
}

//===============================================
void SAL_CALL PluginProgress::addEventListener(const css::uno::Reference< css::lang::XEventListener >& )
    throw(css::uno::RuntimeException)
{
}

//===============================================
void SAL_CALL PluginProgress::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& )
    throw(css::uno::RuntimeException)
{
}

//===============================================
void SAL_CALL PluginProgress::start(const ::rtl::OUString&,
                                          sal_Int32        nRange)
    throw(css::uno::RuntimeException)
{
    if (m_xProgress.is())
        m_xProgress->start(::rtl::OUString(), nRange);
}

//===============================================
void SAL_CALL PluginProgress::end()
    throw(css::uno::RuntimeException)
{
    if (m_xProgress.is())
        m_xProgress->end();
}

//===============================================
void SAL_CALL PluginProgress::setText(const ::rtl::OUString& sText)
    throw(css::uno::RuntimeException)
{
    if (m_xProgress.is())
        m_xProgress->setText(sText);
}

//===============================================
void SAL_CALL PluginProgress::setValue(sal_Int32 nValue)
    throw(css::uno::RuntimeException)
{
    if (m_xProgress.is())
        m_xProgress->setValue(nValue);
}

//===============================================
void SAL_CALL PluginProgress::reset()
    throw(css::uno::RuntimeException)
{
    if (m_xProgress.is())
        m_xProgress->reset();
}

//===============================================
SaveDialog::SaveDialog(Window*       pParent,
                       RecoveryCore* pCore  )
    : IExtendedTabPage( pParent, SVX_RES( RID_SVXPAGE_DOCRECOVERY_SAVE ) )
    , m_aTitleWin    ( this   , SVX_RES  ( WIN_SAVE_TITLE              ) )
    , m_aTitleFT     ( this   , SVX_RES  ( FT_SAVE_TITLE               ) )
    , m_aTitleFL     ( this   , SVX_RES  ( FL_SAVE_TITLE               ) )
    , m_aDescrFT     ( this   , SVX_RES  ( FT_SAVE_DESCR               ) )
    , m_aFileListFT  ( this   , SVX_RES  ( FT_SAVE_FILELIST            ) )
    , m_aFileListLB  ( this   , SVX_RES  ( LB_SAVE_FILELIST            ) )
    , m_aBottomFL    ( this   , SVX_RES  ( FL_SAVE_BOTTOM              ) )
    , m_aOkBtn       ( this   , SVX_RES  ( BT_SAVE_OK                  ) )
    , m_pCore        ( pCore                                           )
{
    FreeResource();

    // Prepare the office for the following crash save step.
    // E.g. hide all open widows so the user cant influence our
    // operation .-)
    m_pCore->doEmergencySavePrepare();

    const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
    Wallpaper aBackground(rStyleSettings.GetWindowColor());
    m_aTitleWin.SetBackground(aBackground);
    m_aTitleFT.SetBackground (aBackground);

    Font aFont(m_aTitleFT.GetFont());
    aFont.SetWeight(WEIGHT_BOLD);
    m_aTitleFT.SetFont(aFont);

    m_aOkBtn.SetClickHdl( LINK( this, SaveDialog, OKButtonHdl ) );
//    m_aFileListLB.EnableInput( sal_False );
    m_aFileListLB.SetControlBackground( rStyleSettings.GetDialogColor() );

    // fill listbox with current open documents
    m_aFileListLB.Clear();

    TURLList*                pURLs = m_pCore->getURLListAccess();
    TURLList::const_iterator pIt;

    for (  pIt  = pURLs->begin();
           pIt != pURLs->end()  ;
         ++pIt                  )
    {
        const TURLInfo& rInfo = *pIt;
        m_aFileListLB.InsertEntry( rInfo.DisplayName, rInfo.StandardImage );
    }
}

//===============================================
SaveDialog::~SaveDialog()
{
}

//===============================================
IMPL_LINK( SaveDialog, OKButtonHdl, void*, EMPTYARG )
{
    m_nResult = DLG_RET_OK;
    return 0;
}

//===============================================
short SaveDialog::execute()
{
    ::vos::OGuard aLock(Application::GetSolarMutex());

    // wait for user input "OK"
    m_nResult = DLG_RET_UNKNOWN;
    while(m_nResult == DLG_RET_UNKNOWN)
        Application::Yield();

    // start crash-save with progress
    if (m_nResult == DLG_RET_OK)
    {
        SaveProgressDialog* pProgress = new SaveProgressDialog(this, m_pCore);
        m_nResult = pProgress->Execute();
        delete pProgress;
    }
    // if "CANCEL" => return "CANCEL"
    // if "OK"     => "AUTOLUNCH" always !
    if (m_nResult == DLG_RET_OK)
        m_nResult = DLG_RET_OK_AUTOLUNCH;

    return m_nResult;
}

//===============================================
void SaveDialog::setDefButton()
{
    m_aOkBtn.GrabFocus();
}

//===============================================
SaveProgressDialog::SaveProgressDialog(Window*       pParent,
                                       RecoveryCore* pCore  )
    : ModalDialog   ( pParent        , SVX_RES( RID_SVX_MDLG_DOCRECOVERY_PROGR ) )
    , m_aHintFT     ( this           , SVX_RES  ( FT_SAVEPROGR_HINT              ) )
    , m_aProgrFT    ( this           , SVX_RES  ( FT_SAVEPROGR_PROGR             ) )
    , m_aProgrParent( this           , SVX_RES  ( WIN_SAVEPROGR_PROGR            ) )
    , m_pCore       ( pCore                                                      )
{
    FreeResource();
    PluginProgress* pProgress   = new PluginProgress( &m_aProgrParent, pCore->getSMGR() );
                    m_xProgress = css::uno::Reference< css::task::XStatusIndicator >(static_cast< css::task::XStatusIndicator* >(pProgress), css::uno::UNO_QUERY_THROW);
//  m_aProgrBaseTxt = m_aProgrFT.GetText();
}

//===============================================
SaveProgressDialog::~SaveProgressDialog()
{
}

//===============================================
short SaveProgressDialog::Execute()
{
    ::vos::OGuard aLock(Application::GetSolarMutex());

    m_pCore->setProgressHandler(m_xProgress);
    m_pCore->setUpdateListener(this);
    m_pCore->doEmergencySave();
    short nRet = ModalDialog::Execute();
    m_pCore->setUpdateListener(0);
    return nRet;
}

//===============================================
void SaveProgressDialog::updateItems()
{
}

//===============================================
void SaveProgressDialog::stepNext(TURLInfo* )
{
    /* TODO

        wenn die m_pCore noch ein Member m_nCurrentItem haette
        koennte man dort erkennen, wer gerade drann war, wer demnaechst
        dran ist ... Diese Info kann man dann in unserem Progress FixText anzeigen ...
    */
}

//===============================================
void SaveProgressDialog::start()
{
}

//===============================================
void SaveProgressDialog::end()
{
    EndDialog(DLG_RET_OK);
}

//===============================================
RecovDocListEntry::RecovDocListEntry(      SvLBoxEntry* pEntry,
                                           USHORT       nFlags,
                                     const String&      sText )
    : SvLBoxString( pEntry, nFlags, sText )
{
}

//===============================================
void RecovDocListEntry::Paint(const Point&       aPos   ,
                                    SvLBox&      aDevice,
                                    USHORT       /*nFlags */,
                                    SvLBoxEntry* pEntry )
{
    const Image*        pImg  = 0;
    const String*       pTxt  = 0;
          RecovDocList* pList = static_cast< RecovDocList* >(&aDevice);

    BOOL      bHC         = aDevice.GetSettings().GetStyleSettings().GetHighContrastMode();

    TURLInfo* pInfo  = (TURLInfo*)pEntry->GetUserData();
    switch(pInfo->RecoveryState)
    {
        case E_SUCCESSFULLY_RECOVERED :
        {
            pImg = &pList->m_aGreenCheckImg;
            if (bHC)
                pImg = &pList->m_aGreenCheckImgHC;
            pTxt = &pList->m_aSuccessRecovStr;
        }
        break;

        case E_ORIGINAL_DOCUMENT_RECOVERED : // TODO must be renamed into ORIGINAL DOCUMENT recovered! Because its marked as yellow
        {
            pImg = &pList->m_aYellowCheckImg;
            if (bHC)
                pImg = &pList->m_aYellowCheckImgHC;
            pTxt = &pList->m_aOrigDocRecovStr;
        }
        break;

        case E_RECOVERY_FAILED :
        {
            pImg = &pList->m_aRedCrossImg;
            if (bHC)
                pImg = &pList->m_aRedCrossImgHC;
            pTxt = &pList->m_aRecovFailedStr;
        }
        break;

        case E_RECOVERY_IS_IN_PROGRESS :
        {
            pImg = 0;
            pTxt = &pList->m_aRecovInProgrStr;
        }
        break;

        case E_NOT_RECOVERED_YET :
        {
            pImg = 0;
            pTxt = &pList->m_aNotRecovYetStr;
        }
        break;
    }

    if (pImg)
        aDevice.DrawImage(aPos, *pImg);

    if (pTxt)
    {
        ::rtl::OUString sT1(*pTxt);

        Point aPnt(aPos);
        aPnt.X() += pList->m_aGreenCheckImg.GetSizePixel().Width();
        aPnt.X() += 10;
        aDevice.DrawText(aPnt, *pTxt);
    }
}
//===============================================
RecovDocList::RecovDocList(      Window* pParent,
                           const ResId&  rResId )
    : SvxSimpleTable      ( pParent, rResId            )
    , m_aGreenCheckImg    ( ResId(IMG_GREENCHECK,*rResId.GetResMgr()     ) )
    , m_aYellowCheckImg   ( ResId(IMG_YELLOWCHECK,*rResId.GetResMgr()    ) )
    , m_aRedCrossImg      ( ResId(IMG_REDCROSS,*rResId.GetResMgr()       ) )
    , m_aGreenCheckImgHC  ( ResId(IMG_GREENCHECK_HC,*rResId.GetResMgr()  ) )
    , m_aYellowCheckImgHC ( ResId(IMG_YELLOWCHECK_HC,*rResId.GetResMgr() ) )
    , m_aRedCrossImgHC    ( ResId(IMG_REDCROSS_HC,*rResId.GetResMgr()    ) )
    , m_aSuccessRecovStr  ( ResId(STR_SUCCESSRECOV,*rResId.GetResMgr()   ) )
    , m_aOrigDocRecovStr  ( ResId(STR_ORIGDOCRECOV,*rResId.GetResMgr()   ) )
    , m_aRecovFailedStr   ( ResId(STR_RECOVFAILED,*rResId.GetResMgr()    ) )
    , m_aRecovInProgrStr  ( ResId(STR_RECOVINPROGR,*rResId.GetResMgr()   ) )
    , m_aNotRecovYetStr   ( ResId(STR_NOTRECOVYET,*rResId.GetResMgr()    ) )
{
    //SetEntryHeight( short( maGreenCheckImg.GetSizePixel().Height() ) );
}

//===============================================
RecovDocList::~RecovDocList()
{
}

//===============================================
void RecovDocList::InitEntry(      SvLBoxEntry* pEntry ,
                             const XubString&   sText  ,
                             const Image&       aImage1,
                             const Image&       aImage2,
                                   SvLBoxButtonKind eButtonKind)
{
    SvTabListBox::InitEntry(pEntry, sText, aImage1, aImage2, eButtonKind);
    DBG_ASSERT( TabCount() == 2, "*RecovDocList::InitEntry(): structure missmatch" );

    SvLBoxString*       pCol = (SvLBoxString*)pEntry->GetItem(2);
    RecovDocListEntry*  p    = new RecovDocListEntry(pEntry, 0, pCol->GetText());
    pEntry->ReplaceItem(p, 2);
}

//===============================================
short impl_askUserForWizardCancel(Window* pParent, sal_Int16 nRes)
{
    QueryBox aQuery(pParent, SVX_RES(nRes));
    if (aQuery.Execute() == RET_YES)
        return DLG_RET_OK;
    else
        return DLG_RET_CANCEL;
}

//===============================================
RecoveryDialog::RecoveryDialog(Window*       pParent,
                               RecoveryCore* pCore  )
    : IExtendedTabPage( pParent      , SVX_RES( RID_SVXPAGE_DOCRECOVERY_RECOVER ) )
    , m_aTitleWin           ( this           , SVX_RES  ( WIN_RECOV_TITLE                ) )
    , m_aTitleFT            ( this           , SVX_RES  ( FT_RECOV_TITLE                 ) )
    , m_aTitleFL            ( this           , SVX_RES  ( FL_RECOV_TITLE                 ) )
    , m_aDescrFT            ( this           , SVX_RES  ( FT_RECOV_DESCR                 ) )
    , m_aProgressFT         ( this           , SVX_RES  ( FT_RECOV_PROGR                 ) )
    , m_aProgrParent        ( this           , SVX_RES  ( WIN_RECOV_PROGR                ) )
    , m_aFileListFT         ( this           , SVX_RES  ( FT_RECOV_FILELIST              ) )
    , m_aFileListLB         ( this           , SVX_RES  ( LB_RECOV_FILELIST              ) )
    , m_aBottomFL           ( this           , SVX_RES  ( FL_RECOV_BOTTOM                ) )
    , m_aNextBtn            ( this           , SVX_RES  ( BTN_RECOV_NEXT                 ) )
    , m_aCancelBtn          ( this           , SVX_RES  ( BTN_RECOV_CANCEL               ) )
    , m_aNextStr            (                  SVX_RES  ( STR_RECOVERY_NEXT              ) )
    , m_aTitleRecoveryInProgress(              SVX_RES  ( STR_RECOVERY_INPROGRESS        ) )
    , m_aTitleRecoveryReport(                  SVX_RES  ( STR_RECOVERY_REPORT            ) )
    , m_aRecoveryOnlyFinish (                  SVX_RES  ( STR_RECOVERYONLY_FINISH        ) )
    , m_aRecoveryOnlyFinishDescr(              SVX_RES  ( STR_RECOVERYONLY_FINISH_DESCR  ) )
    , m_pDefButton          ( NULL                                                       )
    , m_pCore               ( pCore                                                      )
    , m_eRecoveryState      (RecoveryDialog::E_RECOVERY_PREPARED)
    , m_bWaitForUser        (sal_False)
    , m_bWaitForCore        (sal_False)
    , m_bUserDecideNext     (sal_False)
    , m_bWasRecoveryStarted (sal_False)
    , m_bRecoveryOnly       (sal_False)
{
    static long nTabs[] = { 2, 0, 40*RECOV_CONTROLWIDTH/100 };
    m_aFileListLB.SetTabs( &nTabs[0] );
    m_aFileListLB.InsertHeaderEntry( String( SVX_RES( STR_HEADERBAR ) ) );

    FreeResource();

    ::rtl::OUString CFG_PACKAGE_RECOVERY( RTL_CONSTASCII_USTRINGPARAM  ( "org.openoffice.Office.Recovery/" ));
    ::rtl::OUString CFG_PATH_CRASHREPORTER( RTL_CONSTASCII_USTRINGPARAM( "CrashReporter"                 ));
    ::rtl::OUString CFG_ENTRY_ENABLED( RTL_CONSTASCII_USTRINGPARAM     ( "Enabled"                       ));

    sal_Bool bCrashRepEnabled( sal_True );
    css::uno::Any aVal = ::comphelper::ConfigurationHelper::readDirectKey(
                                pCore->getSMGR(),
                                CFG_PACKAGE_RECOVERY,
                                CFG_PATH_CRASHREPORTER,
                                CFG_ENTRY_ENABLED,
                                ::comphelper::ConfigurationHelper::E_READONLY);
    aVal >>= bCrashRepEnabled;
    m_bRecoveryOnly = !bCrashRepEnabled;

    PluginProgress* pProgress   = new PluginProgress( &m_aProgrParent, pCore->getSMGR() );
                    m_xProgress = css::uno::Reference< css::task::XStatusIndicator >(static_cast< css::task::XStatusIndicator* >(pProgress), css::uno::UNO_QUERY_THROW);

    const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
    Wallpaper aBackground( rStyleSettings.GetWindowColor() );
    m_aTitleWin.SetBackground(aBackground);
    m_aTitleFT.SetBackground (aBackground);

    Font aFont(m_aTitleFT.GetFont());
    aFont.SetWeight(WEIGHT_BOLD);
    m_aTitleFT.SetFont(aFont);

    m_aFileListLB.SetBackground( rStyleSettings.GetDialogColor() );

    m_aNextBtn.Enable(TRUE);
    m_aNextBtn.SetClickHdl( LINK( this, RecoveryDialog, NextButtonHdl ) );
    m_aCancelBtn.SetClickHdl( LINK( this, RecoveryDialog, CancelButtonHdl ) );

    // fill list box first time
    TURLList*                pURLList = m_pCore->getURLListAccess();
    TURLList::const_iterator pIt;
    for (  pIt  = pURLList->begin();
           pIt != pURLList->end()  ;
         ++pIt                     )
    {
        const TURLInfo& rInfo = *pIt;

        String sName( rInfo.DisplayName );
        sName += '\t';
        sName += impl_getStatusString( rInfo );
        SvLBoxEntry* pEntry = m_aFileListLB.InsertEntry(sName, rInfo.StandardImage, rInfo.StandardImage);
        pEntry->SetUserData((void*)&rInfo);
        m_aFileListLB.SetExpandedEntryBmp (pEntry, rInfo.HCImage, BMP_COLOR_HIGHCONTRAST);
        m_aFileListLB.SetCollapsedEntryBmp(pEntry, rInfo.HCImage, BMP_COLOR_HIGHCONTRAST);
    }

    // mark first item
    SvLBoxEntry* pFirst = m_aFileListLB.First();
    if (pFirst)
        m_aFileListLB.SetCursor(pFirst, sal_True);
}

//===============================================
RecoveryDialog::~RecoveryDialog()
{
}

//===============================================
short RecoveryDialog::execute()
{
    ::vos::OGuard aSolarLock(Application::GetSolarMutex());

    switch(m_eRecoveryState)
    {
        case RecoveryDialog::E_RECOVERY_PREPARED :
             {
                // Dialog was started first time ...
                // wait for user decision ("start" or "cancel" recovery)
                // This decision will be made inside the NextBtn handler.
                m_aNextBtn.Enable(TRUE);
                m_aCancelBtn.Enable(TRUE);
                m_bWaitForUser = sal_True;
                while(m_bWaitForUser)
                    Application::Yield();
                if (m_bUserDecideNext)
                    m_eRecoveryState = RecoveryDialog::E_RECOVERY_IN_PROGRESS;
                else
                    m_eRecoveryState = RecoveryDialog::E_RECOVERY_CANCELED;
                return execute();
             }

        case RecoveryDialog::E_RECOVERY_IN_PROGRESS :
             {
                // user decided to start recovery ...
                m_bWasRecoveryStarted = sal_True;
                // do it asynchronous (to allow repaints)
                // and wait for this asynchronous operation.
                m_aDescrFT.SetText( m_aTitleRecoveryInProgress );
                m_aNextBtn.Enable(FALSE);
                m_aCancelBtn.Enable(FALSE);
                m_pCore->setProgressHandler(m_xProgress);
                m_pCore->setUpdateListener(this);
                m_pCore->doRecovery();

                m_bWaitForCore = sal_True;
                while(m_bWaitForCore)
                    Application::Yield();

                m_pCore->setUpdateListener(0);
                m_eRecoveryState = RecoveryDialog::E_RECOVERY_CORE_DONE;
                return execute();
             }

        case RecoveryDialog::E_RECOVERY_CORE_DONE :
             {
                 // the core finished it's task.
                 // let the user decide the next step.
                 if ( m_bRecoveryOnly )
                 {
                     m_aDescrFT.SetText(m_aRecoveryOnlyFinishDescr);
                     m_aNextBtn.SetText(m_aRecoveryOnlyFinish);
                     m_aNextBtn.Enable(TRUE);
                     m_aCancelBtn.Enable(FALSE);
                 }
                 else
                 {
                    m_aDescrFT.SetText(m_aTitleRecoveryReport);
                    m_aNextBtn.SetText(m_aNextStr);
                    m_aNextBtn.Enable(TRUE);
                    m_aCancelBtn.Enable(TRUE);
                 }

                 m_bWaitForUser = sal_True;
                 while(m_bWaitForUser)
                     Application::Yield();

                if (m_bUserDecideNext)
                    m_eRecoveryState = RecoveryDialog::E_RECOVERY_DONE;
                else
                    m_eRecoveryState = RecoveryDialog::E_RECOVERY_CANCELED;
                return execute();
             }

        case RecoveryDialog::E_RECOVERY_DONE :
             {
                 // All documents was reovered.
                 // User decided to step to the "next" wizard page.
                 // Do it ... but check first, if there exist some
                 // failed recovery documents. They must be saved to
                 // a user selected directrory.
                 short                 nRet                  = DLG_RET_UNKNOWN;
                 BrokenRecoveryDialog* pBrokenRecoveryDialog = new BrokenRecoveryDialog(this, m_pCore, !m_bWasRecoveryStarted);
                 String                sSaveDir              = pBrokenRecoveryDialog->getSaveDirURL(); // get the default dir
                 if (pBrokenRecoveryDialog->isExecutionNeeded())
                 {
                     nRet = pBrokenRecoveryDialog->Execute();
                     sSaveDir = pBrokenRecoveryDialog->getSaveDirURL();
                 }
                 delete pBrokenRecoveryDialog;

                 switch(nRet)
                 {
                     // no broken temp files exists
                     // step to the next wizard page
                     case DLG_RET_UNKNOWN :
                          {
                              m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
                              return DLG_RET_OK;
                          }

                     // user decided to save the broken temp files
                     // do and forget it
                     // step to the next wizard page
                     case DLG_RET_OK :
                          {
                              m_pCore->saveBrokenTempEntries(sSaveDir);
                              m_pCore->forgetBrokenTempEntries();
                              m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
                              return DLG_RET_OK;
                          }

                     // user decided to ignore broken temp files.
                     // Ask it again ... may be this decision was wrong.
                     // Results:
                     //     IGNORE => remove broken temp files
                     //            => step to the next wizard page
                     //     CANCEL => step back to the recovery page
                     case DLG_RET_CANCEL :
                          {
                              // TODO ask user ...
                              m_pCore->forgetBrokenTempEntries();
                              m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
                              return DLG_RET_OK;
                          }
                 }

                 m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;
                 return DLG_RET_OK;
             }

        case RecoveryDialog::E_RECOVERY_CANCELED :
             {
                 // "YES" => break recovery
                 // But there exist different states, where "cancel" can be called.
                 // Handle it different.
                 if (m_bWasRecoveryStarted)
                     m_eRecoveryState = RecoveryDialog::E_RECOVERY_CANCELED_AFTERWARDS;
                 else
                     m_eRecoveryState = RecoveryDialog::E_RECOVERY_CANCELED_BEFORE;
                 return execute();
             }

        case RecoveryDialog::E_RECOVERY_CANCELED_BEFORE :
        case RecoveryDialog::E_RECOVERY_CANCELED_AFTERWARDS :
             {
                 // We have to check if there exists some temp. files.
                 // They should be saved to a user defined location.
                 // If no temp files exists or user decided to ignore it ...
                 // we have to remove all recovery/session data anyway!
                 short                 nRet                  = DLG_RET_UNKNOWN;
                 BrokenRecoveryDialog* pBrokenRecoveryDialog = new BrokenRecoveryDialog(this, m_pCore, !m_bWasRecoveryStarted);
                 String                sSaveDir              = pBrokenRecoveryDialog->getSaveDirURL(); // get the default save location

                 // dialog itself checks if there is a need to copy files for this mode.
                 // It uses the information m_bWasRecoveryStarted doing so.
                 if (pBrokenRecoveryDialog->isExecutionNeeded())
                 {
                     nRet     = pBrokenRecoveryDialog->Execute();
                     sSaveDir = pBrokenRecoveryDialog->getSaveDirURL();
                 }
                 delete pBrokenRecoveryDialog;

                 // Possible states:
                 // a) nRet == DLG_RET_UNKNOWN
                 //         dialog was not shown ...
                 //         because there exists no temp file for copy.
                 //         => remove all recovery data
                 // b) nRet == DLG_RET_OK
                 //         dialog was shown ...
                 //         user decided to save temp files
                 //         => save all OR broken temp files (depends from the time, where cancel was called)
                 //         => remove all recovery data
                 // c) nRet == DLG_RET_CANCEL
                 //         dialog was shown ...
                 //         user decided to ignore temp files
                 //         => remove all recovery data
                 // => a)/c) are the same ... b) has one additional operation

                 // b)
                 if (nRet == DLG_RET_OK)
                 {
                     if (m_bWasRecoveryStarted)
                         m_pCore->saveBrokenTempEntries(sSaveDir);
                     else
                         m_pCore->saveAllTempEntries(sSaveDir);
                 }

                 // a,b,c)
                 if (m_bWasRecoveryStarted)
                    m_pCore->forgetBrokenRecoveryEntries();
                 else
                    m_pCore->forgetAllRecoveryEntries();
                 m_eRecoveryState = RecoveryDialog::E_RECOVERY_HANDLED;

                 // THERE IS NO WAY BACK. see impl_askUserForWizardCancel()!
                 return DLG_RET_CANCEL;
             }

        case RecoveryDialog::E_RECOVERY_HANDLED :
             {
                 m_bWaitForUser = sal_True;
                 while(m_bWaitForUser)
                     Application::Yield();

                 // TODO: show BrokenRecoveryDialog again, ift he user
                 // doesnt accepted it last time.

                 if (m_bUserDecideNext)
                     return DLG_RET_OK;
                 else
                     return DLG_RET_CANCEL;
             }
    }

    // should never be reached .-)
    DBG_ERROR("Should never be reached!");
    return DLG_RET_OK;
}

//===============================================
void RecoveryDialog::setDefButton()
{
    if ( m_aNextBtn.IsEnabled() )
        m_aNextBtn.GrabFocus();
    else
        m_pDefButton = &m_aNextBtn;
}

//===============================================
void RecoveryDialog::start()
{
}

//===============================================
void RecoveryDialog::updateItems()
{
    ULONG c = m_aFileListLB.GetEntryCount();
    ULONG i = 0;
    for ( i=0; i<c; ++i )
    {
        SvLBoxEntry* pEntry = m_aFileListLB.GetEntry(i);
        if ( !pEntry )
            continue;

        TURLInfo* pInfo = (TURLInfo*)pEntry->GetUserData();
        if ( !pInfo )
            continue;

        String sStatus = impl_getStatusString( *pInfo );
        if ( sStatus.Len() > 0 )
            m_aFileListLB.SetEntryText( sStatus, pEntry, 1 );
    }

    m_aFileListLB.Invalidate();
    m_aFileListLB.Update();
}

//===============================================
void RecoveryDialog::stepNext(TURLInfo* pItem)
{
    ULONG c = m_aFileListLB.GetEntryCount();
    ULONG i = 0;
    for (i=0; i<c; ++i)
    {
        SvLBoxEntry* pEntry = m_aFileListLB.GetEntry(i);
        if (!pEntry)
            continue;

        TURLInfo* pInfo = (TURLInfo*)pEntry->GetUserData();
        if (pInfo->ID != pItem->ID)
            continue;

        m_aFileListLB.SetCursor(pEntry, sal_True);
        m_aFileListLB.MakeVisible(pEntry);
        m_aFileListLB.Invalidate();
        m_aFileListLB.Update();
        break;
    }
}

//===============================================
void RecoveryDialog::end()
{
    if ( m_pDefButton )
    {
        m_pDefButton->GrabFocus();
        m_pDefButton = NULL;
    }
    m_bWaitForCore = sal_False;
}

//===============================================
IMPL_LINK( RecoveryDialog, NextButtonHdl, void*, EMPTYARG )
{
    m_bUserDecideNext = sal_True;
    m_bWaitForUser    = sal_False;
    return 0;
}

//===============================================
IMPL_LINK( RecoveryDialog, CancelButtonHdl, void*, EMPTYARG )
{
    if (m_eRecoveryState == RecoveryDialog::E_RECOVERY_PREPARED)
    {
        if (impl_askUserForWizardCancel(this, RID_SVXQB_EXIT_RECOVERY) == DLG_RET_CANCEL)
            return 0;
    }
    m_bUserDecideNext = sal_False;
    m_bWaitForUser    = sal_False;
    return 0;
}

//===============================================
void RecoveryDialog::impl_refreshDocList()
{
}

//===============================================
String RecoveryDialog::impl_getStatusString( const TURLInfo& rInfo ) const
{
    String sStatus;
    switch ( rInfo.RecoveryState )
    {
        case E_SUCCESSFULLY_RECOVERED :
            sStatus = m_aFileListLB.m_aSuccessRecovStr;
            break;
        case E_ORIGINAL_DOCUMENT_RECOVERED :
            sStatus = m_aFileListLB.m_aOrigDocRecovStr;
            break;
        case E_RECOVERY_FAILED :
            sStatus = m_aFileListLB.m_aRecovFailedStr;
            break;
        case E_RECOVERY_IS_IN_PROGRESS :
            sStatus = m_aFileListLB.m_aRecovInProgrStr;
            break;
        case E_NOT_RECOVERED_YET :
            sStatus = m_aFileListLB.m_aNotRecovYetStr;
            break;
        default:
            break;
    }
    return sStatus;
}

//===============================================
BrokenRecoveryDialog::BrokenRecoveryDialog(Window*       pParent        ,
                                           RecoveryCore* pCore          ,
                                           sal_Bool      bBeforeRecovery)
    : ModalDialog   ( pParent, SVX_RES( RID_SVX_MDLG_DOCRECOVERY_BROKEN ) )
    , m_aDescrFT    ( this   , SVX_RES( FT_BROKEN_DESCR                   ) )
    , m_aFileListFT ( this   , SVX_RES( FT_BROKEN_FILELIST                ) )
    , m_aFileListLB ( this   , SVX_RES( LB_BROKEN_FILELIST                ) )
    , m_aSaveDirFT  ( this   , SVX_RES( FT_BROKEN_SAVEDIR                 ) )
    , m_aSaveDirED  ( this   , SVX_RES( ED_BROKEN_SAVEDIR                 ) )
    , m_aSaveDirBtn ( this   , SVX_RES( BTN_BROKEN_SAVEDIR                ) )
    , m_aBottomFL   ( this   , SVX_RES( FL_BROKEN_BOTTOM                  ) )
    , m_aOkBtn      ( this   , SVX_RES( BTN_BROKEN_OK                     ) )
    , m_aCancelBtn  ( this   , SVX_RES( BTN_BROKEN_CANCEL                 ) )
    , m_pCore       ( pCore                                               )
    , m_bBeforeRecovery (bBeforeRecovery)
    , m_bExecutionNeeded(sal_False)
{
    FreeResource();

    m_aSaveDirBtn.SetClickHdl( LINK( this, BrokenRecoveryDialog, SaveButtonHdl ) );
    m_aOkBtn.SetClickHdl( LINK( this, BrokenRecoveryDialog, OkButtonHdl ) );
    m_aCancelBtn.SetClickHdl( LINK( this, BrokenRecoveryDialog, CancelButtonHdl ) );

    m_sSavePath = SvtPathOptions().GetWorkPath();
    INetURLObject aObj( m_sSavePath );
    String sPath;
    ::utl::LocalFileHelper::ConvertURLToSystemPath( aObj.GetMainURL( INetURLObject::NO_DECODE ), sPath );
    m_aSaveDirED.SetText( sPath );

    impl_refresh();
}

//===============================================
BrokenRecoveryDialog::~BrokenRecoveryDialog()
{
}

//===============================================
void BrokenRecoveryDialog::impl_refresh()
{
                             m_bExecutionNeeded = sal_False;
    TURLList*                pURLList           = m_pCore->getURLListAccess();
    TURLList::const_iterator pIt;
    for (  pIt  = pURLList->begin();
           pIt != pURLList->end()  ;
         ++pIt                     )
    {
        const TURLInfo& rInfo = *pIt;

        if (m_bBeforeRecovery)
        {
            // "Cancel" before recovery ->
            // search for any temp files!
            if (!rInfo.TempURL.getLength())
                continue;
        }
        else
        {
            // "Cancel" after recovery ->
            // search for broken temp files
            if (!RecoveryCore::isBrokenTempEntry(rInfo))
                continue;
        }

        m_bExecutionNeeded = sal_True;

        USHORT nPos = m_aFileListLB.InsertEntry(rInfo.DisplayName, rInfo.StandardImage );
        m_aFileListLB.SetEntryData( nPos, (void*)&rInfo );
    }
    m_sSavePath = ::rtl::OUString();
    m_aOkBtn.GrabFocus();
}

//===============================================
sal_Bool BrokenRecoveryDialog::isExecutionNeeded()
{
    return m_bExecutionNeeded;
}

//===============================================
::rtl::OUString BrokenRecoveryDialog::getSaveDirURL()
{
    return m_sSavePath;
}

//===============================================
IMPL_LINK( BrokenRecoveryDialog, OkButtonHdl, void*, EMPTYARG )
{
    String sPhysicalPath = m_aSaveDirED.GetText().EraseLeadingChars().EraseTrailingChars();
    String sURL;
    ::utl::LocalFileHelper::ConvertPhysicalNameToURL( sPhysicalPath, sURL );
    m_sSavePath = sURL;
    while (!m_sSavePath.getLength())
        impl_askForSavePath();

    EndDialog(DLG_RET_OK);
    return 0;
}

//===============================================
IMPL_LINK( BrokenRecoveryDialog, CancelButtonHdl, void*, EMPTYARG )
{
    EndDialog(DLG_RET_CANCEL);
    return 0;
}

//===============================================
IMPL_LINK( BrokenRecoveryDialog, SaveButtonHdl, void*, EMPTYARG )
{
    impl_askForSavePath();
    return 0;
}

//===============================================
void BrokenRecoveryDialog::impl_askForSavePath()
{
    css::uno::Reference< css::ui::dialogs::XFolderPicker > xFolderPicker(
        m_pCore->getSMGR()->createInstance(SERVICENAME_FOLDERPICKER), css::uno::UNO_QUERY_THROW);
//  svt::SetDialogHelpId( xFolderPicker, HID_OPTIONS_PATHS_SELECTFOLDER );

    INetURLObject aURL(m_sSavePath, INET_PROT_FILE);
    xFolderPicker->setDisplayDirectory(aURL.GetMainURL(INetURLObject::NO_DECODE));
    short nRet = xFolderPicker->execute();
    if (nRet == css::ui::dialogs::ExecutableDialogResults::OK)
    {
        m_sSavePath = xFolderPicker->getDirectory();
        String sPath;
        ::utl::LocalFileHelper::ConvertURLToSystemPath( m_sSavePath, sPath );
        m_aSaveDirED.SetText( sPath );
    }
}

//===============================================
    ///////////////////////////////////////////////////////////////////////
    // Error Report Welcome Dialog
    ///////////////////////////////////////////////////////////////////////

    ErrorRepWelcomeDialog::ErrorRepWelcomeDialog( Window* _pParent, sal_Bool _bAllowBack )
            :IExtendedTabPage        ( _pParent, SVX_RES( RID_SVXPAGE_ERR_REP_WELCOME ) )
            ,maTitleWin     ( this, SVX_RES( WIN_RECOV_TITLE ) )
            ,maTitleFT      ( this, SVX_RES( FT_RECOV_TITLE ) )
            ,maTitleFL      ( this, SVX_RES( FL_RECOV_TITLE ) )
            ,maDescrFT      ( this, SVX_RES( FT_RECOV_DESCR ) )
            ,maBottomFL     ( this, SVX_RES( FL_RECOV_BOTTOM ) )
            ,maPrevBtn      ( this, SVX_RES( BTN_RECOV_PREV ) )
            ,maNextBtn      ( this, SVX_RES( BTN_RECOV_NEXT ) )
            ,maCancelBtn    ( this, SVX_RES( BTN_RECOV_CANCEL ) )
        {
            FreeResource();

            Wallpaper       aBack( GetSettings().GetStyleSettings().GetWindowColor() );
            maTitleWin.SetBackground( aBack );
            maTitleFT.SetBackground( aBack );

            Font    aFnt( maTitleFT.GetFont() );
            aFnt.SetWeight( WEIGHT_BOLD );
            maTitleFT.SetFont( aFnt );

            maPrevBtn.SetClickHdl( LINK( this, ErrorRepWelcomeDialog, PrevBtnHdl ) );
            maPrevBtn.Enable( _bAllowBack );

            maNextBtn.SetClickHdl( LINK( this, ErrorRepWelcomeDialog, NextBtnHdl ) );
            maNextBtn.Enable( sal_True );

            maCancelBtn.SetClickHdl( LINK( this, ErrorRepWelcomeDialog, CancelBtnHdl ) );
            maCancelBtn.Enable( sal_True );
        }

        ErrorRepWelcomeDialog::~ErrorRepWelcomeDialog()
        {
        }

        IMPL_LINK( ErrorRepWelcomeDialog, PrevBtnHdl, void*, EMPTYARG )
        {
            m_nResult = DLG_RET_BACK;
            return 0;
        }

        IMPL_LINK( ErrorRepWelcomeDialog, NextBtnHdl, void*, EMPTYARG )
        {
            m_nResult = DLG_RET_OK;
            return 0;
        }

        IMPL_LINK( ErrorRepWelcomeDialog, CancelBtnHdl, void*, EMPTYARG )
        {
            m_nResult = DLG_RET_CANCEL;
            return 0;
        }

        short ErrorRepWelcomeDialog::execute()
        {
            ::vos::OGuard aLock(Application::GetSolarMutex());
            Show();
            m_nResult = DLG_RET_UNKNOWN;
            while(m_nResult == DLG_RET_UNKNOWN)
                Application::Yield();
            return m_nResult;
        }

        void ErrorRepWelcomeDialog::setDefButton()
        {
            maNextBtn.GrabFocus();
        }

    ///////////////////////////////////////////////////////////////////////
    // Error Report Send Dialog and its MultiLineEdit
    ///////////////////////////////////////////////////////////////////////

        ErrorDescriptionEdit::ErrorDescriptionEdit( Window* pParent, const ResId& rResId ) :

            MultiLineEdit( pParent, rResId )

        {
            SetModifyHdl( LINK( this, ErrorDescriptionEdit, ModifyHdl ) );
            if ( GetVScrollBar() )
                GetVScrollBar()->Hide();
        }

        ErrorDescriptionEdit::~ErrorDescriptionEdit()
        {
        }

        IMPL_LINK( ErrorDescriptionEdit, ModifyHdl, void*, EMPTYARG )
        {
            if ( !GetVScrollBar() )
                return 0;

            ExtTextEngine* pTextEngine = GetTextEngine();
            DBG_ASSERT( pTextEngine, "no text engine" );

            ULONG i, nParaCount = pTextEngine->GetParagraphCount();
            USHORT nLineCount = 0;

            for ( i = 0; i < nParaCount; ++i )
                nLineCount = nLineCount + pTextEngine->GetLineCount(i);

            USHORT nVisCols = 0, nVisLines = 0;
            GetMaxVisColumnsAndLines( nVisCols, nVisLines );
            GetVScrollBar()->Show( nLineCount > nVisLines );

            return 0;
        }

        ErrorRepSendDialog::ErrorRepSendDialog( Window* _pParent )
            :IExtendedTabPage       ( _pParent, SVX_RES( RID_SVXPAGE_ERR_REP_SEND ) )
            ,maTitleWin     ( this, SVX_RES( WIN_RECOV_TITLE ) )
            ,maTitleFT      ( this, SVX_RES( FT_RECOV_TITLE ) )
            ,maTitleFL      ( this, SVX_RES( FL_RECOV_TITLE ) )
            ,maDescrFT      ( this, SVX_RES( FT_RECOV_DESCR ) )

            ,maDocTypeFT    ( this, SVX_RES( FT_ERRSEND_DOCTYPE ) )
            ,maDocTypeED    ( this, SVX_RES( ED_ERRSEND_DOCTYPE ) )
            ,maUsingFT      ( this, SVX_RES( FT_ERRSEND_USING ) )
            ,maUsingML      ( this, SVX_RES( ML_ERRSEND_USING ) )
            ,maShowRepBtn   ( this, SVX_RES( BTN_ERRSEND_SHOWREP ) )
            ,maOptBtn       ( this, SVX_RES( BTN_ERRSEND_OPT ) )
            ,maContactCB    ( this, SVX_RES( CB_ERRSEND_CONTACT ) )
            ,maEMailAddrFT  ( this, SVX_RES( FT_ERRSEND_EMAILADDR ) )
            ,maEMailAddrED  ( this, SVX_RES( ED_ERRSEND_EMAILADDR ) )

            ,maBottomFL     ( this, SVX_RES( FL_RECOV_BOTTOM ) )
            ,maPrevBtn      ( this, SVX_RES( BTN_RECOV_PREV ) )
            ,maNextBtn      ( this, SVX_RES( BTN_RECOV_NEXT ) )
            ,maCancelBtn    ( this, SVX_RES( BTN_RECOV_CANCEL ) )
        {
            FreeResource();

            initControls();

            Wallpaper aBack( GetSettings().GetStyleSettings().GetWindowColor() );
            maTitleWin.SetBackground( aBack );
            maTitleFT.SetBackground( aBack );

            Font aFnt( maTitleFT.GetFont() );
            aFnt.SetWeight( WEIGHT_BOLD );
            maTitleFT.SetFont( aFnt );

            maShowRepBtn.SetClickHdl( LINK( this, ErrorRepSendDialog, ShowRepBtnHdl ) );
            maOptBtn.SetClickHdl( LINK( this, ErrorRepSendDialog, OptBtnHdl ) );
            maContactCB.SetClickHdl( LINK( this, ErrorRepSendDialog, ContactCBHdl ) );
            maPrevBtn.SetClickHdl( LINK( this, ErrorRepSendDialog, PrevBtnHdl ) );
            maNextBtn.SetClickHdl( LINK( this, ErrorRepSendDialog, SendBtnHdl ) );
            maCancelBtn.SetClickHdl( LINK( this, ErrorRepSendDialog, CancelBtnHdl ) );

            ReadParams();

            /*
            maDocTypeED.SetText( maParams.maSubject );
            maUsingML.SetText( maParams.maBody );
            maContactCB.Check( maParams.mbAllowContact );
            maEMailAddrED.SetText( maParams.maReturnAddress );
            */
            ContactCBHdl( 0 );
        }

        ErrorRepSendDialog::~ErrorRepSendDialog()
        {
        }

        short ErrorRepSendDialog::execute()
        {
            ::vos::OGuard aLock(Application::GetSolarMutex());
            Show();
            m_nResult = DLG_RET_UNKNOWN;
            while(m_nResult == DLG_RET_UNKNOWN)
                Application::Yield();
            return m_nResult;
        }

        void ErrorRepSendDialog::setDefButton()
        {
            // set first focus
            maDocTypeED.GrabFocus();
        }

        IMPL_LINK( ErrorRepSendDialog, PrevBtnHdl, void*, EMPTYARG )
        {
            m_nResult = DLG_RET_BACK;
            return 0;
        }

        IMPL_LINK( ErrorRepSendDialog, CancelBtnHdl, void*, EMPTYARG )
        {
            m_nResult = DLG_RET_CANCEL;
            return 0;
        }

        IMPL_LINK( ErrorRepSendDialog, SendBtnHdl, void*, EMPTYARG )
        {

            SaveParams();
            SendReport();

            m_nResult = DLG_RET_OK;
            return 0;
        }

        IMPL_LINK( ErrorRepSendDialog, ShowRepBtnHdl, void*, EMPTYARG )
        {
            ErrorRepPreviewDialog aDlg( this );
            aDlg.Execute();
            return 0;
        }

        IMPL_LINK( ErrorRepSendDialog, OptBtnHdl, void*, EMPTYARG )
        {
            ErrorRepOptionsDialog aDlg( this, maParams );
            aDlg.Execute();
            return 0;
        }

        IMPL_LINK( ErrorRepSendDialog, ContactCBHdl, void*, EMPTYARG )
        {
            bool    bCheck = maContactCB.IsChecked();
            maEMailAddrFT.Enable( bCheck );
            maEMailAddrED.Enable( bCheck );
            return 0;
        }

        void ErrorRepSendDialog::initControls()
        {
            // if the text is too short for two lines, insert a newline
            String sText = maDocTypeFT.GetText();
            if ( maDocTypeFT.GetCtrlTextWidth( sText ) <= maDocTypeFT.GetSizePixel().Width() )
            {
                sText.Insert( '\n', 0 );
                maDocTypeFT.SetText( sText );
            }

            // if the button text is too wide, then broaden the button
            sText = maShowRepBtn.GetText();
            long nTxtW = maShowRepBtn.GetCtrlTextWidth( sText );
            long nBtnW = maShowRepBtn.GetSizePixel().Width();
            if ( nTxtW >= nBtnW )
            {
                const long nMinDelta = 10;
                long nDelta = Max( nTxtW - nBtnW, nMinDelta );
                sal_uInt32 i = 0;
                Window* pWins[] =
                {
                    &maShowRepBtn, &maOptBtn,
                    &maDescrFT, &maDocTypeFT, &maDocTypeED, &maUsingFT,
                    &maUsingML, &maContactCB, &maEMailAddrFT, &maEMailAddrED
                };
                // the first two buttons need a new size (wider) and position (more left)
                Window** pCurrent = pWins;
                const sal_uInt32 nBtnCount = 2;
                for ( ; i < nBtnCount; ++i, ++pCurrent )
                {
                    Size aNewSize = (*pCurrent)->GetSizePixel();
                    aNewSize.Width() += nDelta;
                    (*pCurrent)->SetSizePixel( aNewSize );
                    Point aNewPos = (*pCurrent)->GetPosPixel();
                    aNewPos.X() -= nDelta;
                    (*pCurrent)->SetPosPixel( aNewPos );
                }

                // loop through all the other windows and adjust their size
                for ( ; i < sizeof( pWins ) / sizeof( pWins[ 0 ] ); ++i, ++pCurrent )
                {
                    Size aSize = (*pCurrent)->GetSizePixel();
                    aSize.Width() -= nDelta;
                    (*pCurrent)->SetSizePixel( aSize );
                }
            }
        }

        String ErrorRepSendDialog::GetDocType( void ) const
        {
            return maDocTypeED.GetText();
        }

        String ErrorRepSendDialog::GetUsing( void ) const
        {
            return maUsingML.GetText();
        }

        bool ErrorRepSendDialog::IsContactAllowed( void ) const
        {
            return maContactCB.IsChecked();
        }

        String ErrorRepSendDialog::GetEMailAddress( void ) const
        {
            return maEMailAddrED.GetText();
        }


    ///////////////////////////////////////////////////////////////////////
    // Error Report Options Dialog
    ///////////////////////////////////////////////////////////////////////

        ErrorRepOptionsDialog::ErrorRepOptionsDialog( Window* _pParent, ErrorRepParams& _rParams )
            :ModalDialog    ( _pParent, SVX_RES( RID_SVX_MDLG_ERR_REP_OPTIONS ) )
            ,maProxyFL( this, SVX_RES( FL_ERROPT_PROXY ) )
            ,maSystemBtn( this, SVX_RES( BTN_ERROPT_SYSTEM ) )
            ,maDirectBtn( this, SVX_RES( BTN_ERROPT_DIRECT ) )
            ,maManualBtn( this, SVX_RES( BTN_ERROPT_MANUAL ) )
            ,maProxyServerFT( this, SVX_RES( FT_ERROPT_PROXYSERVER ) )
            ,maProxyServerEd( this, SVX_RES( ED_ERROPT_PROXYSERVER ) )
            ,maProxyPortFT( this, SVX_RES( FT_ERROPT_PROXYPORT ) )
            ,maProxyPortEd( this, SVX_RES( ED_ERROPT_PROXYPORT ) )
            ,maDescriptionFT( this, SVX_RES( FT_ERROPT_DESCRIPTION ) )
            ,maButtonsFL( this, SVX_RES( FL_ERROPT_BUTTONS ) )
            ,maOKBtn( this, SVX_RES( BTN_ERROPT_OK ) )
            ,maCancelBtn( this, SVX_RES( BTN_ERROPT_CANCEL ) )
            ,mrParams( _rParams )
        {
            FreeResource();

            maManualBtn.SetToggleHdl( LINK( this, ErrorRepOptionsDialog, ManualBtnHdl ) );
            maCancelBtn.SetClickHdl( LINK( this, ErrorRepOptionsDialog, CancelBtnHdl ) );
            maOKBtn.SetClickHdl( LINK( this, ErrorRepOptionsDialog, OKBtnHdl ) );

            maProxyServerEd.SetText( mrParams.maHTTPProxyServer );
            maProxyPortEd.SetText( mrParams.maHTTPProxyPort );

#ifndef WNT
            // no "Use system settings" button on non windows systems
            // so hide this button
            maSystemBtn.Hide();
            long nDelta = maDirectBtn.GetPosPixel().Y() - maSystemBtn.GetPosPixel().Y();
            // and loop through all these controls and adjust their position
            Window* pWins[] =
            {
                &maDirectBtn, &maManualBtn, &maProxyServerFT,
                &maProxyServerEd, &maProxyPortFT, &maProxyPortEd, &maDescriptionFT
            };
            Window** pCurrent = pWins;
            for ( sal_uInt32 i = 0; i < sizeof( pWins ) / sizeof( pWins[ 0 ] ); ++i, ++pCurrent )
            {
                Point aPos = (*pCurrent)->GetPosPixel();
                aPos.Y() -= nDelta;
                (*pCurrent)->SetPosPixel( aPos );
            }
#endif


            switch ( mrParams.miHTTPConnectionType )
            {
            default:
#ifdef WNT
            case 0:
                maSystemBtn.Check( TRUE );
                break;
#endif
            case 1:
                maDirectBtn.Check( TRUE );
                break;
            case 2:
                maManualBtn.Check( TRUE );
                break;
            }

            ManualBtnHdl( 0 );
        }

        ErrorRepOptionsDialog::~ErrorRepOptionsDialog()
        {
        }

        IMPL_LINK( ErrorRepOptionsDialog, ManualBtnHdl, void*, EMPTYARG )
        {
            bool    bCheck = maManualBtn.IsChecked();
            maProxyServerFT.Enable( bCheck );
            maProxyServerEd.Enable( bCheck );
            maProxyPortFT.Enable( bCheck );
            maProxyPortEd.Enable( bCheck );
            return 0;
        }

        IMPL_LINK( ErrorRepOptionsDialog, OKBtnHdl, void*, EMPTYARG )
        {
            if ( maManualBtn.IsChecked() )
                mrParams.miHTTPConnectionType = 2;
            else if ( maDirectBtn.IsChecked() )
                mrParams.miHTTPConnectionType = 1;
            else if ( maSystemBtn.IsChecked() )
                mrParams.miHTTPConnectionType = 0;

            mrParams.maHTTPProxyServer = maProxyServerEd.GetText();
            mrParams.maHTTPProxyPort = maProxyPortEd.GetText();

            EndDialog(DLG_RET_OK);
            return 0;
        }

        IMPL_LINK( ErrorRepOptionsDialog, CancelBtnHdl, void*, EMPTYARG )
        {
            EndDialog(DLG_RET_CANCEL);
            return 0;
        }

    ///////////////////////////////////////////////////////////////////////
    // Error Report Edit (MultiLineEdit with fixed font)
    ///////////////////////////////////////////////////////////////////////

        ErrorRepEdit::ErrorRepEdit( Window* pParent, const ResId& rResId ) :
            ExtMultiLineEdit( pParent, rResId )
        {
            // fixed font for error report
            Color   aColor  = GetTextColor();

            Font aFont = OutputDevice::GetDefaultFont(
                DEFAULTFONT_FIXED, LANGUAGE_SYSTEM, DEFAULTFONT_FLAGS_ONLYONE );

            // Set font color because the default font color is transparent !!!
            aFont.SetColor( aColor );

            GetTextEngine()->SetFont( aFont );

            // no blinking cursor and a little left margin
            EnableCursor( FALSE );
            SetLeftMargin( 4 );
        }

        ErrorRepEdit::~ErrorRepEdit()
        {
        }

    ///////////////////////////////////////////////////////////////////////
    // Error Report Preview Dialog
    ///////////////////////////////////////////////////////////////////////


        static ::rtl::OUString GetCrashConfigDir()
        {

#if defined(WNT) || defined(OS2)
            OUString    ustrValue = OUString::createFromAscii("${$BRAND_BASE_DIR/program/bootstrap.ini:UserInstallation}");
#elif defined( MACOSX )
            OUString    ustrValue = OUString::createFromAscii("~");
#else
            OUString    ustrValue = OUString::createFromAscii("$SYSUSERCONFIG");
#endif
            Bootstrap::expandMacros( ustrValue );

#if defined(WNT) || defined(OS2)
            ustrValue += OUString::createFromAscii("/user/crashdata");
#endif
            return ustrValue;
        }

#if defined(WNT) || defined(OS2)
#define CHKFILE "crashdat.chk"
#define STKFILE "crashdat.stk"
#define PRVFILE "crashdat.prv"
#else
#define CHKFILE ".crash_report_checksum"
#define STKFILE ".crash_report_frames"
#define PRVFILE ".crash_report_preview"
#endif

//      static ::rtl::OUString GetChecksumURL()
//      {
//          ::rtl::OUString aURL = GetCrashConfigDir();

//          aURL += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) );
//          aURL += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( CHKFILE ) );

//          return aURL;
//      }

//      static ::rtl::OUString GetStackURL()
//      {
//          ::rtl::OUString aURL = GetCrashConfigDir();

//          aURL += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) );
//          aURL += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STKFILE ) );

//          return aURL;
//      }

        static ::rtl::OUString GetPreviewURL()
        {
            ::rtl::OUString aURL = GetCrashConfigDir();

            aURL += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) );
            aURL += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( PRVFILE ) );

            return aURL;
        }

        static String LoadCrashFile( const ::rtl::OUString &rURL )
        {
            String  aFileContent;
            ::osl::File aFile( rURL );

            printf( "Loading %s:", OString( rURL.getStr(), rURL.getLength(), osl_getThreadTextEncoding() ).getStr() );
            if ( ::osl::FileBase::E_None == aFile.open( OpenFlag_Read ) )
            {
                ::rtl::OString  aContent;
                ::osl::FileBase::RC result;
                sal_uInt64  aBytesRead;

                do
                {
                    sal_Char    aBuffer[256];

                    result = aFile.read( aBuffer, sizeof(aBuffer), aBytesRead );

                    if ( ::osl::FileBase::E_None == result )
                    {
                        ::rtl::OString  aTemp( aBuffer, static_cast< xub_StrLen >( aBytesRead ) );
                        aContent += aTemp;
                    }
                } while ( ::osl::FileBase::E_None == result && aBytesRead );

                ::rtl::OUString ustrContent( aContent.getStr(), aContent.getLength(), RTL_TEXTENCODING_UTF8 );
                aFileContent = ustrContent;

                aFile.close();

                printf( "SUCCEEDED\n" );
            }
            else
                printf( "FAILED\n" );

            return aFileContent;
        }



        ErrorRepPreviewDialog::ErrorRepPreviewDialog( Window* _pParent )
            :ModalDialog    ( _pParent, SVX_RES( RID_SVX_MDLG_ERR_REP_PREVIEW ) )
            ,maContentML( this, SVX_RES( ML_ERRPREVIEW_CONTENT ) )
            ,maOKBtn( this, SVX_RES( BTN_ERRPREVIEW_OK ) )

        {
            FreeResource();

            mnMinHeight = ( maContentML.GetSizePixel().Height() / 2 );

            String  aPreview = LoadCrashFile( GetPreviewURL() );
            ErrorRepSendDialog *pMainDlg = (ErrorRepSendDialog *)_pParent;

            String aSeperator = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "\r\n\r\n================\r\n\r\n" ) );

            String aContent = pMainDlg->GetDocType();
            if ( aContent.Len() > 0 )
                aContent += aSeperator;
            aContent += pMainDlg->GetUsing();
            if ( aContent.Len() > 0 )
                aContent += aSeperator;
            aContent += aPreview;

            maContentML.SetText( aContent );
        }

        ErrorRepPreviewDialog::~ErrorRepPreviewDialog()
        {
        }

        void ErrorRepPreviewDialog::Resize()
        {
            Size a3Sz = LogicToPixel( Size( 3, 3 ), MAP_APPFONT );
            Size aWinSz = GetSizePixel();
            Size aBtnSz = maOKBtn.GetSizePixel();
            Point aEditPnt = maContentML.GetPosPixel();

            long nNewHeight = Max( aWinSz.Height() - aEditPnt.Y() - 3 * a3Sz.Height() - aBtnSz.Height(), mnMinHeight );
            long nNewWidth = aWinSz.Width() - 4 * a3Sz.Width();

            Size aNewSize( nNewWidth, nNewHeight );
            maContentML.SetSizePixel( aNewSize );
            Point aNewPoint( Max( aEditPnt.X() + aNewSize.Width() - aBtnSz.Width(), aEditPnt.X() ),
                             aEditPnt.Y() + aNewSize.Height() + a3Sz.Height() );
            maOKBtn.SetPosPixel( aNewPoint );
        }
    }   // namespace DocRecovery
}   // namespace svx