/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/

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

// include ---------------------------------------------------------------

#include <tools/ref.hxx>
#include <tools/shl.hxx>
#include <vcl/wrkwin.hxx>
#include <vcl/menu.hxx>
#include <vcl/msgbox.hxx>
#include <vcl/scrbar.hxx>
#include <SpellAttrib.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/bindings.hxx>
#include <svl/undo.hxx>
#include <unotools/lingucfg.hxx>
#include <svtools/textdata.hxx>
#include <svtools/filter.hxx>
#include <editeng/unolingu.hxx>
#include <editeng/splwrap.hxx>
#include <linguistic/lngprops.hxx>
#include <linguistic/misc.hxx>
#include <comphelper/processfactory.hxx>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XServiceDisplayName.hpp>
#include <com/sun/star/linguistic2/SpellFailure.hpp>
#include <com/sun/star/frame/XStorable.hpp>
#include <sfx2/app.hxx>
#include <vcl/help.hxx>
#include <vcl/graph.hxx>
#include <osl/file.hxx>
#include <cuires.hrc>
#include <helpid.hrc>
#include "SpellDialog.hrc"
#include <editeng/optitems.hxx>
#include <editeng/svxenum.hxx>
#include <svx/SpellDialogChildWindow.hxx>
#include "SpellDialog.hxx"
#include <svx/dlgutil.hxx>
#include "optlingu.hxx"
#include <dialmgr.hxx>
#include <svx/svxerr.hxx>
#include "treeopt.hxx"
#include <svtools/langtab.hxx>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::linguistic2;

using ::rtl::OUString;

#define C2U(cChar) 					::rtl::OUString::createFromAscii(cChar)
// struct SpellDialog_Impl ---------------------------------------------

struct SpellDialog_Impl
{
	Sequence< Reference< XDictionary >  >	aDics;
};
// -----------------------------------------------------------------------
//#define VENDOR_IMAGE_HEIGHT 44 //as specified

#define SPELLUNDO_START                     200

#define SPELLUNDO_CHANGE_LANGUAGE           (SPELLUNDO_START + 1)
#define SPELLUNDO_CHANGE_TEXTENGINE         (SPELLUNDO_START + 2)
#define SPELLUNDO_CHANGE_NEXTERROR          (SPELLUNDO_START + 3)
#define SPELLUNDO_CHANGE_ADD_TO_DICTIONARY  (SPELLUNDO_START + 4)
#define SPELLUNDO_CHANGE_GROUP              (SPELLUNDO_START + 5) //undo list
#define SPELLUNDO_MOVE_ERROREND             (SPELLUNDO_START + 6)
#define SPELLUNDO_UNDO_EDIT_MODE            (SPELLUNDO_START + 7)
#define SPELLUNDO_ADD_IGNORE_RULE           (SPELLUNDO_START + 8)

namespace svx{
class SpellUndoAction_Impl : public SfxUndoAction
{
	sal_uInt16          m_nId;
	const Link&     m_rActionLink;
	// undo of button enabling
	bool            m_bEnableChangePB;
	bool            m_bEnableChangeAllPB;
	// undo of MarkNextError - used in change and change all, ignore and ignore all
	long            m_nNewErrorStart;
	long            m_nNewErrorEnd;
	long            m_nOldErrorStart;
	long            m_nOldErrorEnd;
	bool            m_bIsErrorLanguageSelected;
	::rtl::OUString m_sRuleId;
	// undo of AddToDictionary
	Reference<XDictionary>  m_xDictionary;
	::rtl::OUString                m_sAddedWord;
	// move end of error - ::ChangeMarkedWord()
	long            m_nOffset;

public:
	SpellUndoAction_Impl(sal_uInt16 nId, const Link& rActionLink) :
		m_nId(nId),
		m_rActionLink( rActionLink),
		m_bEnableChangePB(false),
		m_bEnableChangeAllPB(false),
		m_nNewErrorStart(-1),
		m_nNewErrorEnd(-1),
		m_nOldErrorStart(-1),
		m_nOldErrorEnd(-1),
		m_bIsErrorLanguageSelected(false),
		m_nOffset(0)
		{}

	~SpellUndoAction_Impl();

	virtual void            Undo();
	virtual sal_uInt16          GetId() const;

    void                    SetEnableChangePB(){m_bEnableChangePB = true;}
    bool                    IsEnableChangePB(){return m_bEnableChangePB;}

    void                    SetEnableChangeAllPB(){m_bEnableChangeAllPB = true;}
    bool                    IsEnableChangeAllPB(){return m_bEnableChangeAllPB;}

    void                    SetErrorMove(long nNewStart, long nNewEnd, long nOldStart, long nOldEnd)
                                {
                                        m_nNewErrorStart = nNewStart;
                                        m_nNewErrorEnd  = nNewEnd;
                                        m_nOldErrorStart = nOldStart;
                                        m_nOldErrorEnd = nOldEnd;
                                }
    long                    GetNewErrorStart() { return m_nNewErrorStart;}
    long                    GetNewErrorEnd() { return m_nNewErrorEnd;}
    long                    GetOldErrorStart() { return m_nOldErrorStart;}
    long                    GetOldErrorEnd() { return m_nOldErrorEnd;}

    void                    SetErrorLanguageSelected(bool bSet){ m_bIsErrorLanguageSelected = bSet;}
    bool                    IsErrorLanguageSelected() const {return m_bIsErrorLanguageSelected;}


    void                    SetDictionary(Reference<XDictionary> xDict) { m_xDictionary = xDict; }
    Reference<XDictionary>  GetDictionary() const {return m_xDictionary;}
    void                    SetAddedWord(const ::rtl::OUString& rWord) {m_sAddedWord = rWord;}
    const ::rtl::OUString&         GetAddedWord() const { return m_sAddedWord;}

    void                    SetOffset(long nSet) {m_nOffset = nSet;}
    long                    GetOffset() const {return m_nOffset;}

    void                    SetErrorType( const ::rtl::OUString& rId ) { m_sRuleId = rId; }
    const ::rtl::OUString&  GetErrorType() const { return m_sRuleId; }

};
}//namespace svx
using namespace ::svx;
/*-- 06.11.2003 12:16:02---------------------------------------------------

  -----------------------------------------------------------------------*/
SpellUndoAction_Impl::~SpellUndoAction_Impl()
{
}
/*-- 06.11.2003 12:16:02---------------------------------------------------

  -----------------------------------------------------------------------*/
void SpellUndoAction_Impl::Undo()
{
    m_rActionLink.Call(this);
}
/*-- 06.11.2003 12:16:02---------------------------------------------------

  -----------------------------------------------------------------------*/
sal_uInt16 SpellUndoAction_Impl::GetId()const
{
    return m_nId;
}

// class SvxSpellCheckDialog ---------------------------------------------

SpellDialog::SpellDialog(
        SpellDialogChildWindow* pChildWindow,
        Window * pParent,
        SfxBindings* _pBindings)
            : SfxModelessDialog (_pBindings,
                                    pChildWindow,
                                    pParent,
                                    CUI_RES(RID_SVXDLG_SPELLCHECK)),

    aVendorImageFI  ( this , CUI_RES( IMG_VENDOR ) ),
    aLanguageFT     ( this, CUI_RES( FT_LANGUAGE ) ),
    aLanguageLB     ( this, CUI_RES( LB_LANGUAGE ) ),
    aNotInDictFT    ( this, CUI_RES( FT_NOTINDICT ) ),
    aSentenceED      ( this, CUI_RES( ED_NEWWORD ) ),
    aSuggestionFT   ( this, CUI_RES( FT_SUGGESTION ) ),
    aSuggestionLB   ( this, CUI_RES( LB_SUGGESTION ) ),

    aIgnorePB       ( this, CUI_RES( PB_IGNORE ) ),
    aIgnoreAllPB    ( this, CUI_RES( PB_IGNOREALL ) ),
    aIgnoreRulePB   ( this, CUI_RES( PB_IGNORERULE ) ),
    aAddToDictMB    ( this, CUI_RES( MB_ADDTODICT ) ),

    aChangePB       ( this, CUI_RES( PB_CHANGE ) ),
    aChangeAllPB    ( this, CUI_RES( PB_CHANGEALL ) ),
    aExplainPB      ( this, CUI_RES( PB_EXPLAIN) ),
    aAutoCorrPB     ( this, CUI_RES( PB_AUTOCORR ) ),

    aCheckGrammarCB ( this, CUI_RES( CB_CHECK_GRAMMAR ) ),

    aHelpPB         ( this, CUI_RES( PB_HELP ) ),
    aOptionsPB      ( this, CUI_RES( PB_OPTIONS ) ),
    aUndoPB         ( this, CUI_RES( PB_UNDO ) ),
    aClosePB        ( this, CUI_RES( PB_CLOSE ) ),
    aBackgroundGB   ( this, CUI_RES( GB_BACKGROUND ) ),

    aVendorImage    ( CUI_RES( IMG_DEFAULT_VENDOR ) ),
    aVendorImageHC  ( CUI_RES( IMG_DEFAULT_VENDOR_HC ) ),

    aResumeST       ( CUI_RES(ST_RESUME )),
    aIgnoreOnceST   ( aIgnorePB.GetText()),
    aNoSuggestionsST( CUI_RES(ST_NOSUGGESTIONS)),
    m_sTitleSpelling              ( CUI_RES( ST_SPELLING                        ) ),
    m_sTitleSpellingGrammar       ( CUI_RES( ST_SPELLING_AND_GRAMMAR            ) ),
    m_sTitleSpellingGrammarVendor ( CUI_RES( ST_SPELLING_AND_GRAMMAR_VENDORNAME ) ),
    aDialogUndoLink( LINK (this, SpellDialog, DialogUndoHdl)),
    bModified( false ),
    bFocusLocked( true ),
    rParent         ( *pChildWindow ),
    nOldLang        ( LANGUAGE_NONE )
{
    FreeResource();
    xSpell = LinguMgr::GetSpellChecker();
    pImpl = new SpellDialog_Impl;

    //HelpIds
    aClosePB.       SetHelpId(HID_SPLDLG_BUTTON_CLOSE    );
    aIgnorePB.      SetHelpId(HID_SPLDLG_BUTTON_IGNORE   );
    aIgnoreAllPB.   SetHelpId(HID_SPLDLG_BUTTON_IGNOREALL);
    aIgnoreRulePB.  SetHelpId(HID_SPLDLG_BUTTON_IGNORERULE);
    aChangePB.      SetHelpId(HID_SPLDLG_BUTTON_CHANGE   );
    aChangeAllPB.   SetHelpId(HID_SPLDLG_BUTTON_CHANGEALL);
    aExplainPB.     SetHelpId(HID_SPLDLG_BUTTON_EXPLAIN );

    aAddToDictMB.SetPopupMenu( new PopupMenu );

	Init_Impl();

	// disable controls if service is missing
	if (!xSpell.is())
		Enable( sal_False );

    Application::PostUserEvent( STATIC_LINK(
                        this, SpellDialog, InitHdl ) );
}

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

SpellDialog::~SpellDialog()
{
    // save possibly modified user-dictionaries
    Reference< XDictionaryList >  xDicList( SvxGetDictionaryList() );
    if (xDicList.is())
    {
        linguistic::SaveDictionaries( xDicList );
    }

    delete aAddToDictMB.GetPopupMenu();
    delete pImpl;
}

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

void SpellDialog::Init_Impl()
{
	// Handler initialisieren
    aClosePB.SetClickHdl(LINK( this, SpellDialog, CancelHdl ) );
    aChangePB.SetClickHdl(LINK( this, SpellDialog, ChangeHdl ) );
    aChangeAllPB.SetClickHdl(LINK( this, SpellDialog, ChangeAllHdl ) );
    aIgnorePB.SetClickHdl(LINK( this, SpellDialog, IgnoreHdl ) );
    aIgnoreAllPB.SetClickHdl(LINK( this, SpellDialog, IgnoreAllHdl ) );
    aIgnoreRulePB.SetClickHdl(LINK( this, SpellDialog, IgnoreAllHdl ) );
    aUndoPB.SetClickHdl(LINK( this, SpellDialog, UndoHdl ) );

    aAutoCorrPB.SetClickHdl( LINK( this, SpellDialog, ExtClickHdl ) );
    aCheckGrammarCB.SetClickHdl( LINK( this, SpellDialog, CheckGrammarHdl ));
    aOptionsPB .SetClickHdl( LINK( this, SpellDialog, ExtClickHdl ) );

    aSuggestionLB.SetDoubleClickHdl( LINK( this, SpellDialog, ChangeHdl ) );

    aSentenceED.SetModifyHdl(LINK ( this, SpellDialog, ModifyHdl) );
    aAddToDictMB.SetActivateHdl(LINK ( this, SpellDialog, MenuButtonActivateHdl ) );
    aAddToDictMB.SetSelectHdl(LINK ( this, SpellDialog, AddToDictionaryHdl ) );
    aLanguageLB.SetSelectHdl(LINK( this, SpellDialog, LanguageSelectHdl ) );

    // initialize language ListBox
    aLanguageLB.SetLanguageList( LANG_LIST_SPELL_USED, sal_False, sal_False, sal_True );

    // get current language
	UpdateBoxes_Impl();

    aSentenceED.ClearModifyFlag();
	SvxGetChangeAllList()->clear();
}

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

void SpellDialog::UpdateBoxes_Impl()
{
	sal_Int32 i;
	aSuggestionLB.Clear();

	const SpellErrorDescription* pSpellErrorDescription = aSentenceED.GetAlternatives();

	LanguageType nAltLanguage = LANGUAGE_NONE;
	//String      aAltWord;
	Sequence< ::rtl::OUString >	aNewWords;
	bool bIsGrammarError = false;
	if( pSpellErrorDescription )
	{
        nAltLanguage    = SvxLocaleToLanguage( pSpellErrorDescription->aLocale );
        //aAltWord       = String( xAlt->getWord() );
        aNewWords       = pSpellErrorDescription->aSuggestions;
        bIsGrammarError = pSpellErrorDescription->bIsGrammarError;
        aExplainPB.SetExplanation(pSpellErrorDescription->sExplanation );
	}
    if( pSpellErrorDescription && pSpellErrorDescription->sDialogTitle.getLength() )
    {
        // use this function to apply the correct image to be used...
        SetTitle_Impl( nAltLanguage );
        // then change the title to the one to be actually used
        SetText( pSpellErrorDescription->sDialogTitle );
    }
    else
        SetTitle_Impl( nAltLanguage );

    SetSelectedLang_Impl( nAltLanguage );

    // Initialize/update user dictionaries after setting the language in the listbox
    InitUserDicts();

	// Alternativen eintragen
	const ::rtl::OUString *pNewWords = aNewWords.getConstArray();
	const sal_Int32 nSize = aNewWords.getLength();
	for ( i = 0; i < nSize; ++i )
	{
		String aTmp( pNewWords[i] );
        if ( LISTBOX_ENTRY_NOTFOUND == aSuggestionLB.GetEntryPos( aTmp ) )
        {
            aSuggestionLB.InsertEntry( aTmp );
            aSuggestionLB.SetEntryFlags(aSuggestionLB.GetEntryCount() - 1, LISTBOX_ENTRY_FLAG_MULTILINE);
        }
	}
    if(!nSize)
        aSuggestionLB.InsertEntry( aNoSuggestionsST );
    aAutoCorrPB.Enable( nSize > 0 );
    //aSentenceED.GrabFocus();

    aSuggestionFT.Enable(nSize > 0);
    aSuggestionLB.Enable(nSize > 0);
    if( nSize )
	{
        aSuggestionLB.SelectEntryPos(0);
	}
    aChangePB.Enable( nSize > 0);
    aChangeAllPB.Enable(nSize > 0);
    bool bShowChangeAll = !bIsGrammarError;
    aChangeAllPB.Show( bShowChangeAll );
    aExplainPB.Show( !bShowChangeAll );
    aLanguageLB.Enable( bShowChangeAll );
    aIgnoreAllPB.Show( bShowChangeAll );
    aAddToDictMB.Show( bShowChangeAll );
    aIgnoreRulePB.Show( !bShowChangeAll );
    aIgnoreRulePB.Enable(pSpellErrorDescription && pSpellErrorDescription->sRuleId.getLength());
    aExplainPB.Enable( aExplainPB.HasExplanation() );
    aAutoCorrPB.Show( bShowChangeAll && rParent.HasAutoCorrection() );

}
// -----------------------------------------------------------------------

void SpellDialog::SpellContinue_Impl(bool bUseSavedSentence, bool bIgnoreCurrentError )
{
	// initially or after the last error of a sentence MarkNextError will fail
	// then GetNextSentence() has to be called followed again by MarkNextError()
	// MarkNextError is not initially called if the UndoEdit mode is active
	bool bNextSentence = false;
    if((!aSentenceED.IsUndoEditMode() && aSentenceED.MarkNextError( bIgnoreCurrentError )) ||
            true == ( bNextSentence = GetNextSentence_Impl(bUseSavedSentence, aSentenceED.IsUndoEditMode()) && aSentenceED.MarkNextError( false )))
    {
        const SpellErrorDescription* pSpellErrorDescription = aSentenceED.GetAlternatives();
        if( pSpellErrorDescription )
        {
			UpdateBoxes_Impl();
            Control* aControls[] =
            {
                &aNotInDictFT,
                &aSentenceED,
                &aLanguageFT,
                0
            };
            sal_Int32 nIdx = 0;
            do
            {
                aControls[nIdx]->Enable(sal_True);
            }
            while(aControls[++nIdx]);


        }
        if( bNextSentence )
        {
            // remove undo if a new sentence is active
            aSentenceED.ResetUndo();
            aUndoPB.Enable(sal_False);
        }
    }
}
/* -----------------10.09.2003 14:04-----------------
    Initialize, asynchronous to prevent virtual calls
    from a constructor
 --------------------------------------------------*/
IMPL_STATIC_LINK( SpellDialog, InitHdl, SpellDialog *, EMPTYARG )
{
    pThis->SetUpdateMode( sal_False );
    // show or hide AutoCorrect depending on the modules abilities
    pThis->aAutoCorrPB.Show(pThis->rParent.HasAutoCorrection());
    pThis->SpellContinue_Impl();
    pThis->aSentenceED.ResetUndo();
    pThis->aUndoPB.Enable(sal_False);

    pThis->LockFocusChanges(true);
    if( pThis->aChangePB.IsEnabled() )
        pThis->aChangePB.GrabFocus();
    else if( pThis->aIgnorePB.IsEnabled() )
        pThis->aIgnorePB.GrabFocus();
    else if( pThis->aClosePB.IsEnabled() )
        pThis->aClosePB.GrabFocus();
    pThis->LockFocusChanges(false);
    // show grammar CheckBox depending on the modules abilities
    bool bHasGrammarChecking = pThis->rParent.HasGrammarChecking();
    pThis->aCheckGrammarCB.Show( bHasGrammarChecking );
    if( !bHasGrammarChecking )
    {
        // resize the dialog to hide the hidden area of the CheckBox
        Size aBackSize = pThis->aBackgroundGB.GetSizePixel();
        sal_Int32 nDiff = pThis->aBackgroundGB.GetPosPixel().Y() + aBackSize.Height()
                            - pThis->aCheckGrammarCB.GetPosPixel().Y();
        aBackSize.Height() -= nDiff;
        pThis->aBackgroundGB.SetSizePixel(aBackSize);
        Button* aButtons[] = { &pThis->aHelpPB, &pThis->aOptionsPB, &pThis->aUndoPB, &pThis->aClosePB, 0 };
        sal_Int32 nButton = 0;
        while( aButtons[nButton])
        {
            Point aPos = aButtons[nButton]->GetPosPixel();
            aPos.Y() -= nDiff;
            aButtons[nButton]->SetPosPixel(aPos);
            ++nButton;
        }
        Size aDlgSize = pThis->GetSizePixel();
        aDlgSize.Height() -= nDiff;
        pThis->SetSizePixel( aDlgSize );
    }
    else
    {
        if( SvtLinguConfig().HasVendorImages( "SpellAndGrammarDialogImage" ) )
        {
            pThis->aVendorImageFI.Show();
            Size aVendorSize = pThis->aVendorImageFI.GetSizePixel();
            Size aImageSize = pThis->aVendorImageFI.GetImage().GetSizePixel();
            if( aImageSize.Height() )
            {
                aVendorSize.Height() = aImageSize.Height();
                if(aVendorSize.Width() < aImageSize.Width())
                    aVendorSize.Width() = aImageSize.Width();
                pThis->aVendorImageFI.SetSizePixel( aVendorSize );
            }
            //aVendorSize.Height() = nDiff;
            sal_Int32 nDiff = aVendorSize.Height();
            pThis->aVendorImageFI.SetSizePixel(aVendorSize);
            Control* aControls[] = {
                &pThis->aLanguageFT,
                &pThis->aLanguageLB,
                &pThis->aNotInDictFT,
                &pThis->aSentenceED,
                &pThis->aSuggestionFT,
                &pThis->aSuggestionLB,
                &pThis->aIgnorePB,
                &pThis->aIgnoreAllPB,
                &pThis->aIgnoreRulePB,
                &pThis->aAddToDictMB,
                &pThis->aChangePB,
                &pThis->aChangeAllPB,
                &pThis->aExplainPB,
                &pThis->aAutoCorrPB,
                &pThis->aCheckGrammarCB,
                &pThis->aHelpPB,
                &pThis->aOptionsPB,
                &pThis->aUndoPB,
                &pThis->aClosePB,
                &pThis->aBackgroundGB,
                0
            };
            sal_Int32 nControl = 0;
            while( aControls[nControl])
            {
                Point aPos = aControls[nControl]->GetPosPixel();
                aPos.Y() += nDiff;
                aControls[nControl]->SetPosPixel(aPos);
                ++nControl;
            }
            Size aDlgSize = pThis->GetSizePixel();
            aDlgSize.Height() += nDiff;
            pThis->SetSizePixel( aDlgSize );
            pThis->Invalidate();
        }
    }
    pThis->aCheckGrammarCB.Check( pThis->rParent.IsGrammarChecking() );
    pThis->SetUpdateMode( sal_True );
    pThis->Show();
    return 0;
};

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

IMPL_LINK( SpellDialog, ExtClickHdl, Button *, pBtn )
{
    if (&aOptionsPB == pBtn)
		StartSpellOptDlg_Impl();
    else if(&aAutoCorrPB == pBtn)
    {
        // get the currently selected wrong word
        String sCurrentErrorText = aSentenceED.GetErrorText();
        //get the wrong word from the XSpellAlternative
        const SpellErrorDescription* pSpellErrorDescription = aSentenceED.GetAlternatives();
        if( pSpellErrorDescription )
        {
            String sWrong(pSpellErrorDescription->sErrorText);
            // if the word has not been edited in the MultiLineEdit then
            // the current suggestion should be used
            // if it's not the 'no suggestions' entry
            if(sWrong == sCurrentErrorText &&
                    aSuggestionLB.IsEnabled() && aSuggestionLB.GetSelectEntryCount() > 0 &&
                    aNoSuggestionsST != aSuggestionLB.GetSelectEntry())
            {
                sCurrentErrorText = aSuggestionLB.GetSelectEntry();
            }
            if(sWrong != sCurrentErrorText)
            {
                SvxPrepareAutoCorrect( sWrong, sCurrentErrorText );
                LanguageType eLang = GetSelectedLang_Impl();
                rParent.AddAutoCorrection( sWrong, sCurrentErrorText, eLang );
            }
        }
	}
	return 0;
}
// -----------------------------------------------------------------------
IMPL_LINK( SpellDialog, CheckGrammarHdl, CheckBox*, pBox )
{
	rParent.SetGrammarChecking( pBox->IsChecked() );
	Impl_Restore();
	return 0;
}

void SpellDialog::StartSpellOptDlg_Impl()
{
    sal_uInt16 aSpellInfos[] =
    {
        SID_ATTR_SPELL,SID_ATTR_SPELL,
        SID_SPELL_MODIFIED, SID_SPELL_MODIFIED,
        SID_AUTOSPELL_CHECK, SID_AUTOSPELL_CHECK,
        0
    };
    SfxItemSet aSet( SFX_APP()->GetPool(), aSpellInfos);
    aSet.Put(SfxSpellCheckItem( xSpell, SID_ATTR_SPELL ));
	SfxSingleTabDialog* pDlg =
		new SfxSingleTabDialog( this, aSet, RID_SFXPAGE_LINGU );
	SfxTabPage* pPage = SvxLinguTabPage::Create( pDlg, aSet );
	( (SvxLinguTabPage*)pPage )->HideGroups( GROUP_MODULES );
	pDlg->SetTabPage( pPage );
	if(RET_OK == pDlg->Execute())
	{

    	// Benutzerbücher anzeigen
	    InitUserDicts();
        const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
        if(pOutSet)
            OfaTreeOptionsDialog::ApplyLanguageOptions(*pOutSet);
    }
	delete pDlg;

}

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

IMPL_LINK( SpellDialog, ChangeHdl, Button *, EMPTYARG )
{
    if(aSentenceED.IsUndoEditMode())
    {
        SpellContinue_Impl();
    }
    else
    {
        aSentenceED.UndoActionStart( SPELLUNDO_CHANGE_GROUP );
        String aString = aSentenceED.GetErrorText();
        // dots are sometimes part of the spelled word but they are not necessarily part of the replacement
        bool bDot = aString.Len() && aString.GetChar(aString.Len() - 1 ) == '.';
        if(aSuggestionLB.IsEnabled() &&
                aSuggestionLB.GetSelectEntryCount()>0 &&
                aNoSuggestionsST != aSuggestionLB.GetSelectEntry())
            aString = aSuggestionLB.GetSelectEntry();
        if(bDot && (!aString.Len() || aString.GetChar(aString.Len() - 1 ) != '.'))
            aString += '.';

        aSentenceED.ChangeMarkedWord(aString, GetSelectedLang_Impl());
        SpellContinue_Impl();
        bModified = false;
        aSentenceED.UndoActionEnd();
    }
    if(!aChangePB.IsEnabled())
        aIgnorePB.GrabFocus();
    return 1;
}


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

IMPL_LINK( SpellDialog, ChangeAllHdl, Button *, EMPTYARG )
{
    aSentenceED.UndoActionStart( SPELLUNDO_CHANGE_GROUP );
    // change the current word first
    String aString = aSentenceED.GetErrorText();
    if(aSuggestionLB.IsEnabled() &&
            aSuggestionLB.GetSelectEntryCount()>0 &&
            aNoSuggestionsST != aSuggestionLB.GetSelectEntry())
        aString = aSuggestionLB.GetSelectEntry();

    LanguageType eLang = GetSelectedLang_Impl();

	// add new word to ChangeAll list
    String  aOldWord( aSentenceED.GetErrorText() );
    SvxPrepareAutoCorrect( aOldWord, aString );
    Reference<XDictionary> aXDictionary( SvxGetChangeAllList(), UNO_QUERY );
    sal_uInt8 nAdded = linguistic::AddEntryToDic( aXDictionary,
            aOldWord , sal_True,
            aString, eLang );

    if(nAdded == DIC_ERR_NONE)
    {
        SpellUndoAction_Impl* pAction = new SpellUndoAction_Impl(
                        SPELLUNDO_CHANGE_ADD_TO_DICTIONARY, aDialogUndoLink);
        pAction->SetDictionary(aXDictionary);
        pAction->SetAddedWord(aOldWord);
        aSentenceED.AddUndoAction(pAction);
    }

    aSentenceED.ChangeMarkedWord(aString, eLang);
	SpellContinue_Impl();
    bModified = false;
    aSentenceED.UndoActionEnd();
    return 1;
}
// -----------------------------------------------------------------------

IMPL_LINK( SpellDialog, IgnoreAllHdl, Button *, pButton )
{
    aSentenceED.UndoActionStart( SPELLUNDO_CHANGE_GROUP );
    // add word to IgnoreAll list
    Reference< XDictionary > aXDictionary( SvxGetIgnoreAllList(), UNO_QUERY );
    // in case the error has been changed manually it has to be restored
    aSentenceED.RestoreCurrentError();
    if( pButton == &aIgnoreRulePB )
    {
        const SpellErrorDescription* pSpellErrorDescription = aSentenceED.GetAlternatives();
        try
        {
            if( pSpellErrorDescription && pSpellErrorDescription->xGrammarChecker.is() )
            {
                pSpellErrorDescription->xGrammarChecker->ignoreRule( pSpellErrorDescription->sRuleId,
                    pSpellErrorDescription->aLocale );
            }
        }
        catch( const uno::Exception& )
        {
        }
    }
    else
    {
        String sErrorText(aSentenceED.GetErrorText());
        sal_uInt8 nAdded = linguistic::AddEntryToDic( aXDictionary,
            sErrorText, sal_False,
            ::rtl::OUString(), LANGUAGE_NONE );
        if(nAdded == DIC_ERR_NONE)
        {
            SpellUndoAction_Impl* pAction = new SpellUndoAction_Impl(
                            SPELLUNDO_CHANGE_ADD_TO_DICTIONARY, aDialogUndoLink);
            pAction->SetDictionary(aXDictionary);
            pAction->SetAddedWord(sErrorText);
            aSentenceED.AddUndoAction(pAction);
        }
    }

	SpellContinue_Impl();
	bModified = false;
	aSentenceED.UndoActionEnd();
	return 1;
}
/*-- 06.11.2003 11:24:08---------------------------------------------------

  -----------------------------------------------------------------------*/
IMPL_LINK( SpellDialog, UndoHdl, Button*, EMPTYARG )
{
	aSentenceED.Undo();
	if(!aSentenceED.GetUndoActionCount())
		aUndoPB.Enable(sal_False);
	return 0;
}
/*-- 06.11.2003 12:19:15---------------------------------------------------

  -----------------------------------------------------------------------*/
IMPL_LINK( SpellDialog, DialogUndoHdl, SpellUndoAction_Impl*, pAction )
{
    switch(pAction->GetId())
    {
        case SPELLUNDO_CHANGE_TEXTENGINE:
        {
            if(pAction->IsEnableChangePB())
                aChangePB.Enable(sal_False);
            if(pAction->IsEnableChangeAllPB())
                aChangeAllPB.Enable(sal_False);
        }
        break;
        case SPELLUNDO_CHANGE_NEXTERROR:
        {
            aSentenceED.MoveErrorMarkTo((sal_uInt16)pAction->GetOldErrorStart(), (sal_uInt16)pAction->GetOldErrorEnd(), false);
            if(pAction->IsErrorLanguageSelected())
            {
                UpdateBoxes_Impl();
            }
        }
        break;
        case SPELLUNDO_CHANGE_ADD_TO_DICTIONARY:
        {
            if(pAction->GetDictionary().is())
                pAction->GetDictionary()->remove(pAction->GetAddedWord());
        }
        break;
        case SPELLUNDO_MOVE_ERROREND :
        {
            if(pAction->GetOffset() != 0)
                aSentenceED.MoveErrorEnd(pAction->GetOffset());
        }
        break;
        case SPELLUNDO_UNDO_EDIT_MODE :
        {
            // refill the dialog with the currently spelled sentence - throw away all changes
            SpellContinue_Impl(true);
        }
        break;
        case SPELLUNDO_ADD_IGNORE_RULE:
            // undo of ignored rules is not supported
        break;
    }

    return 0;
}
// -----------------------------------------------------------------------
void SpellDialog::Impl_Restore()
{
    //clear the "ChangeAllList"
    SvxGetChangeAllList()->clear();
    //get a new sentence
    aSentenceED.SetText(rtl::OUString());
    aSentenceED.ResetModified();
    SpellContinue_Impl(true);
    aIgnorePB.SetText(aIgnoreOnceST);
}

IMPL_LINK( SpellDialog, IgnoreHdl, Button *, EMPTYARG )
{
    if(aIgnorePB.GetText() == aResumeST)
    {
        Impl_Restore();
    }
    else
    {
        // in case the error has been changed manually it has to be restored,
        // since the users choice now was to ignore the error
        aSentenceED.RestoreCurrentError();

        // the word is being ignored
        SpellContinue_Impl( false, true );
    }
	return 1;
}


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

sal_Bool SpellDialog::Close()
{
    GetBindings().GetDispatcher()->
        Execute(rParent.GetType(),
        SFX_CALLMODE_ASYNCHRON|SFX_CALLMODE_RECORD);
    return sal_True;
}
// -----------------------------------------------------------------------

void SpellDialog::SetSelectedLang_Impl( LanguageType nLang )
{
    aLanguageLB.SelectLanguage( nLang );
}

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

LanguageType SpellDialog::GetSelectedLang_Impl() const
{
    sal_Int16 nLang = aLanguageLB.GetSelectLanguage();
	return nLang;
}
/* -----------------28.10.2003 14:27-----------------

 --------------------------------------------------*/
IMPL_LINK(SpellDialog, LanguageSelectHdl, SvxLanguageBox*, pBox)
{
    //if currently an error is selected then search for alternatives for
    //this word and fill the alternatives ListBox accordingly
    String sError = aSentenceED.GetErrorText();
    aSuggestionLB.Clear();
    if(sError.Len())
    {
        LanguageType eLanguage = pBox->GetSelectLanguage();
        Reference <XSpellAlternatives> xAlt = xSpell->spell( sError, eLanguage,
                                            Sequence< PropertyValue >() );
        if( xAlt.is() )
            aSentenceED.SetAlternatives( xAlt );
        else
        {
            aSentenceED.ChangeMarkedWord( sError, eLanguage );
            SpellContinue_Impl();
        }

         aSentenceED.AddUndoAction(new SpellUndoAction_Impl(SPELLUNDO_CHANGE_LANGUAGE, aDialogUndoLink));
    }

	// Update listboxes and user dictionaries when selected language changes
	SpellDialog::UpdateBoxes_Impl();
	return 0;
}
// -----------------------------------------------------------------------

void SpellDialog::SetLanguage( sal_uInt16 nLang )

/*	[Beschreibung]

	wenn die Sprache im Thesaurus umgestellt wurde,
	muss auch hier die Sprache umgestellt werden.
*/

{
	SetTitle_Impl( nLang );

	// den richtigen Eintrag finden, da sortiert
	aLanguageLB.SelectLanguage( nLang );
}
/*-- 16.06.2008 11:27:02---------------------------------------------------

  -----------------------------------------------------------------------*/
static Image lcl_GetImageFromPngUrl( const ::rtl::OUString &rFileUrl )
{
    Image aRes;
    ::rtl::OUString aTmp;
    osl::FileBase::getSystemPathFromFileURL( rFileUrl, aTmp );
    Graphic aGraphic;
    const String aFilterName( RTL_CONSTASCII_USTRINGPARAM( IMP_PNG ) );
    if( GRFILTER_OK == GraphicFilter::LoadGraphic( aTmp, aFilterName, aGraphic ) )
    {
        aRes = Image( aGraphic.GetBitmapEx() );
    }
    return aRes;
}
void SpellDialog::SetTitle_Impl(LanguageType nLang)
{
    String sTitle( m_sTitleSpelling );
    if( rParent.HasGrammarChecking() )
    {
        String sVendor;
        const SpellErrorDescription* pSpellErrorDescription = aSentenceED.GetAlternatives();
        if( pSpellErrorDescription && pSpellErrorDescription->sServiceName.getLength() )
        {
            bool bHighContrast = GetSettings().GetStyleSettings().GetHighContrastMode();
            ::rtl::OUString sSuggestionImageUrl =
                SvtLinguConfig().GetSpellAndGrammarDialogImage( pSpellErrorDescription->sServiceName, bHighContrast );
            aVendorImageFI.SetImage( lcl_GetImageFromPngUrl( sSuggestionImageUrl ) );
            uno::Reference< lang::XServiceDisplayName > xDisplayName( pSpellErrorDescription->xGrammarChecker, uno::UNO_QUERY );
            if( xDisplayName.is() )
                sVendor = xDisplayName->getServiceDisplayName( pSpellErrorDescription->aLocale );
        }
        else
        {
            bool bHighContrast = GetSettings().GetStyleSettings().GetHighContrastMode();
            aVendorImageFI.SetImage( bHighContrast ? aVendorImageHC : aVendorImage );
        }

        if( sVendor.Len() )
        {
            sTitle = m_sTitleSpellingGrammarVendor;
            sTitle.SearchAndReplaceAscii( "$VendorName", sVendor );
        }
        else
        {
            //bool bHighContrast = GetSettings().GetStyleSettings().GetHighContrastMode();
            sTitle = m_sTitleSpellingGrammar;
        }
    }
    sTitle.SearchAndReplaceAscii( "$LANGUAGE ($LOCATION)", SvtLanguageTable::GetLanguageString(nLang) );
    SetText( sTitle );
}
/*-------------------------------------------------------------------------

  -----------------------------------------------------------------------*/
void SpellDialog::InitUserDicts()
{
    bool bEnable = false;

    // get list of dictionaries
    Reference< XDictionaryList >  xDicList( SvxGetDictionaryList() );
    if (xDicList.is())
    {
        // add active, positive dictionary to dic-list (if not already done).
        // This is to ensure that there is at least one dictionary to which
        // words could be added.
        Reference< XDictionary >  xDic( SvxGetOrCreatePosDic( xDicList ) );
        if (xDic.is())
            xDic->setActive( sal_True );

        pImpl->aDics = xDicList->getDictionaries();

        // this is redundant, there will always be *at least* one dictionary
        bEnable = pImpl->aDics.getLength();
    }

    aAddToDictMB.Enable( bEnable );
}

IMPL_LINK(SpellDialog, MenuButtonActivateHdl, MenuButton*, )
{
	bool bEnable = false;
	const LanguageType nLang = aLanguageLB.GetSelectLanguage();
	const Reference< XDictionary >  *pDic = 0;

	SvtLinguConfig aCfg;
	const bool bHC = Application::GetSettings().GetStyleSettings().GetHighContrastMode();

	// list suitable dictionaries
	const sal_Int32 nSize = pImpl->aDics.getLength();
	pDic = pImpl->aDics.getConstArray();

	PopupMenu* pMenu = aAddToDictMB.GetPopupMenu();
	OSL_ENSURE( pMenu, "svx::SpellDialog::MenuButtonActivateHdl - no PopupMenu!" );
	pMenu->Clear();
	pMenu->SetMenuFlags(MENU_FLAG_NOAUTOMNEMONICS);

    sal_uInt16 nItemId = 1; // menu items should be enumerated from 1 and not 0
    for (sal_Int32 i = 0; i < nSize; ++i)
    {
        uno::Reference< linguistic2::XDictionary >  xDicTmp( pDic[i], uno::UNO_QUERY );
        if (!xDicTmp.is() || SvxGetIgnoreAllList() == xDicTmp)
            continue;

        uno::Reference< frame::XStorable > xStor( xDicTmp, uno::UNO_QUERY );
        LanguageType nActLanguage = SvxLocaleToLanguage( xDicTmp->getLocale() );
        if( xDicTmp->isActive()
            &&  xDicTmp->getDictionaryType() != linguistic2::DictionaryType_NEGATIVE
            && (nLang == nActLanguage || LANGUAGE_NONE == nActLanguage )
            && (!xStor.is() || !xStor->isReadonly()) )
        {
            pMenu->InsertItem( nItemId, xDicTmp->getName() );
            bEnable = sal_True;

            uno::Reference< lang::XServiceInfo > xSvcInfo( xDicTmp, uno::UNO_QUERY );
            if (xSvcInfo.is())
            {
                OUString aDictionaryImageUrl( aCfg.GetSpellAndGrammarContextDictionaryImage(
                        xSvcInfo->getImplementationName(), bHC) );
                if (aDictionaryImageUrl.getLength() > 0)
                {
                    Image aImage( lcl_GetImageFromPngUrl( aDictionaryImageUrl ) );
                    pMenu->SetItemImage( nItemId, aImage );
                }
            }

			++nItemId;
		}
	}

	aAddToDictMB.Enable( bEnable );

	return 0;
}

/*-- 20.10.2003 15:31:06---------------------------------------------------

  -----------------------------------------------------------------------*/
IMPL_LINK(SpellDialog, AddToDictionaryHdl, MenuButton*, pButton )
{
    aSentenceED.UndoActionStart( SPELLUNDO_CHANGE_GROUP );

    //GetErrorText() returns the current error even if the text is already
    //manually changed
    const String aNewWord= aSentenceED.GetErrorText();

    sal_uInt16 nItemId = pButton->GetCurItemId();
    PopupMenu *pMenu = pButton->GetPopupMenu();
    String aDicName ( pMenu->GetItemText( nItemId ) );

    uno::Reference< linguistic2::XDictionary >      xDic;
    uno::Reference< linguistic2::XDictionaryList >  xDicList( SvxGetDictionaryList() );
    if (xDicList.is())
        xDic = xDicList->getDictionaryByName( aDicName );

    sal_Int16 nAddRes = DIC_ERR_UNKNOWN;
    if (xDic.is())
    {
        nAddRes = linguistic::AddEntryToDic( xDic, aNewWord, sal_False, OUString(), LANGUAGE_NONE );
        // save modified user-dictionary if it is persistent
        uno::Reference< frame::XStorable >  xSavDic( xDic, uno::UNO_QUERY );
        if (xSavDic.is())
            xSavDic->store();

        if (nAddRes == DIC_ERR_NONE)
        {
            SpellUndoAction_Impl* pAction = new SpellUndoAction_Impl(
                            SPELLUNDO_CHANGE_ADD_TO_DICTIONARY, aDialogUndoLink);
            pAction->SetDictionary( xDic );
            pAction->SetAddedWord( aNewWord );
            aSentenceED.AddUndoAction( pAction );
        }
        // failed because there is already an entry?
        if (DIC_ERR_NONE != nAddRes && xDic->getEntry( aNewWord ).is())
            nAddRes = DIC_ERR_NONE;
    }
    if (DIC_ERR_NONE != nAddRes)
    {
        SvxDicError( this, nAddRes );
        return 0; // Nicht weitermachen
    }

	// go on
	SpellContinue_Impl();
	aSentenceED.UndoActionEnd();
	return 0;
}
/*-------------------------------------------------------------------------

  -----------------------------------------------------------------------*/
IMPL_LINK(SpellDialog, ModifyHdl, SentenceEditWindow_Impl*, pEd)
{
	if (&aSentenceED == pEd)
	{
        bModified = true;
        aSuggestionLB.SetNoSelection();
        aSuggestionLB.Disable();
        String sNewText( aSentenceED.GetText() );
        aAutoCorrPB.Enable( sNewText != aSentenceED.GetText() );
        SpellUndoAction_Impl* pSpellAction = new SpellUndoAction_Impl(SPELLUNDO_CHANGE_TEXTENGINE, aDialogUndoLink);
        if(!aChangeAllPB.IsEnabled())
        {
            aChangeAllPB.Enable();
            pSpellAction->SetEnableChangeAllPB();
        }
        if(!aChangePB.IsEnabled())
        {
            aChangePB.Enable();
            pSpellAction->SetEnableChangePB();
        }
        aSentenceED.AddUndoAction(pSpellAction);
	}
	return 0;
};
/*-------------------------------------------------------------------------

  -----------------------------------------------------------------------*/
IMPL_LINK(SpellDialog, CancelHdl, Button *, EMPTYARG )
{
	//apply changes and ignored text parts first - if there are any
	rParent.ApplyChangedSentence(aSentenceED.CreateSpellPortions(true), false);
	Close();
	return 0;
}
/*-------------------------------------------------------------------------

  -----------------------------------------------------------------------*/
void SpellDialog::Paint( const Rectangle& rRect )
{
	ModelessDialog::Paint(rRect );
	Rectangle aRect(aBackgroundGB.GetPosPixel(), aBackgroundGB.GetSizePixel());
	DecorationView aDecoView( this );
	aDecoView.DrawButton( aRect, BUTTON_DRAW_NOFILL );
}
/*-- 28.10.2003 13:26:39---------------------------------------------------

  -----------------------------------------------------------------------*/
long SpellDialog::Notify( NotifyEvent& rNEvt )
{
    /* #i38338#
    *   FIXME: LoseFocus and GetFocus are signals from vcl that
    *   a window actually got/lost the focus, it never should be
    *   forwarded from another window, that is simply wrong.
    *   FIXME: overloading the virtual methods GetFocus and LoseFocus
    *   in SpellDialogChildWindow by making them pure is at least questionable.
    *   The only sensible thing would be to call the new Method differently,
    *   e.g. DialogGot/LostFocus or so.
    */
    if( IsVisible() && !bFocusLocked )
    {
        if( rNEvt.GetType() == EVENT_GETFOCUS )
        {
            // notify the child window of the focus change
            rParent.GetFocus();
        }
        else if( rNEvt.GetType() == EVENT_LOSEFOCUS )
        {
            // notify the child window of the focus change
            rParent.LoseFocus();
        }
    }
    return SfxModelessDialog::Notify(rNEvt);
}
/* -----------------10.09.2003 08:26-----------------

 --------------------------------------------------*/
void SpellDialog::InvalidateDialog()
{
    if( bFocusLocked )
        return;
    aIgnorePB.SetText(aResumeST);
    Window* aDisableArr[] =
            {
                &aNotInDictFT,
                &aSentenceED,
                &aSuggestionFT,
                &aSuggestionLB,
                &aLanguageFT,
                &aLanguageLB,
                &aIgnoreAllPB,
                &aIgnoreRulePB,
                &aAddToDictMB,
                &aChangePB,
                &aChangeAllPB,
                &aAutoCorrPB,
                &aUndoPB,
                0
            };
    sal_Int16 i = 0;
	while(aDisableArr[i])
    {
        aDisableArr[i]->Enable(sal_False);
        i++;
    }
    SfxModelessDialog::Deactivate();
}

/*-- 10.09.2003 08:35:56---------------------------------------------------

  -----------------------------------------------------------------------*/
bool SpellDialog::GetNextSentence_Impl(bool bUseSavedSentence, bool bRecheck)
{
    bool bRet = false;
    if(!bUseSavedSentence /*&& aSentenceED.IsModified()*/)
    {
        //apply changes and ignored text parts
        rParent.ApplyChangedSentence(aSentenceED.CreateSpellPortions(true), bRecheck);
    }
    aSentenceED.ResetIgnoreErrorsAt();
    aSentenceED.ResetModified();
    SpellPortions aSentence = bUseSavedSentence ? m_aSavedSentence : rParent.GetNextWrongSentence( bRecheck );
    if(!bUseSavedSentence)
        m_aSavedSentence = aSentence;
    bool bHasReplaced = false;
    while(aSentence.size())
    {
        //apply all changes that are already part of the "ChangeAllList"
        //returns true if the list still contains errors after the changes have been applied

        if(!ApplyChangeAllList_Impl(aSentence, bHasReplaced))
        {
            rParent.ApplyChangedSentence(aSentence, bRecheck);
			aSentence = rParent.GetNextWrongSentence( bRecheck );
        }
		else
            break;
    }

    if(aSentence.size())
    {
        SpellPortions::iterator aStart = aSentence.begin();
        rtl::OUString sText;
        while(aStart != aSentence.end())
        {
            // hidden text has to be ignored
            if(!aStart->bIsHidden)
                sText += aStart->sText;
            aStart++;
        }
        aSentenceED.SetText(sText);
        aStart = aSentence.begin();
        sal_Int32 nStartPosition = 0;
        sal_Int32 nEndPosition = 0;

        while(aStart != aSentence.end())
        {
            // hidden text has to be ignored
            if(!aStart->bIsHidden)
            {
                nEndPosition += aStart->sText.getLength();
                if(aStart->xAlternatives.is())
                {
                    uno::Reference< container::XNamed > xNamed( aStart->xAlternatives, uno::UNO_QUERY );
                    ::rtl::OUString sServiceName;
                    if( xNamed.is() )
                        sServiceName = xNamed->getName();
                    SpellErrorDescription aDesc( false, aStart->xAlternatives->getWord(),
                                    aStart->xAlternatives->getLocale(), aStart->xAlternatives->getAlternatives(), 0, sServiceName);
                    aSentenceED.SetAttrib( SpellErrorAttrib(aDesc), 0, (sal_uInt16) nStartPosition, (sal_uInt16) nEndPosition );
                }
                else if(aStart->bIsGrammarError )
                {
                    uno::Reference< lang::XServiceInfo > xInfo( aStart->xGrammarChecker, uno::UNO_QUERY );
                    SpellErrorDescription aDesc( true,
                        aStart->sText,
						SvxCreateLocale( aStart->eLanguage ),
                        aStart->aGrammarError.aSuggestions,
                        aStart->xGrammarChecker,
                        xInfo->getImplementationName(),
                        &aStart->sDialogTitle,
                        &aStart->aGrammarError.aFullComment,
                        &aStart->aGrammarError.aRuleIdentifier );
                    aSentenceED.SetAttrib( SpellErrorAttrib(aDesc), 0, (sal_uInt16) nStartPosition, (sal_uInt16) nEndPosition );
                }
                if(aStart->bIsField)
                    aSentenceED.SetAttrib( SpellBackgroundAttrib(COL_LIGHTGRAY), 0, (sal_uInt16) nStartPosition, (sal_uInt16) nEndPosition );
                aSentenceED.SetAttrib( SpellLanguageAttrib(aStart->eLanguage), 0, (sal_uInt16) nStartPosition, (sal_uInt16) nEndPosition );
                nStartPosition = nEndPosition;
            }
            aStart++;
        }
        //the edit field needs to be modified to apply the change from the ApplyChangeAllList
        if(!bHasReplaced)
            aSentenceED.ClearModifyFlag();
        aSentenceED.ResetUndo();
        aUndoPB.Enable(sal_False);
        bRet = nStartPosition > 0;
    }
    return bRet;
}
/*-- 12.11.2003 15:21:25---------------------------------------------------
    replace errors that have a replacement in the ChangeAllList
    returns false if the result doesn't contain errors after the replacement
  -----------------------------------------------------------------------*/
bool SpellDialog::ApplyChangeAllList_Impl(SpellPortions& rSentence, bool &bHasReplaced)
{
    bHasReplaced = false;
    bool bRet = true;
    SpellPortions::iterator aStart = rSentence.begin();
    Reference<XDictionary> xChangeAll( SvxGetChangeAllList(), UNO_QUERY );
    if(!xChangeAll->getCount())
        return bRet;
    bRet = false;
    while(aStart != rSentence.end())
    {
        if(aStart->xAlternatives.is())
        {
            Reference<XDictionaryEntry> xEntry = xChangeAll->getEntry( aStart->sText );
            if(xEntry.is())
            {
                aStart->sText = xEntry->getReplacementText();
                aStart->xAlternatives = 0;
                bHasReplaced = true;
            }
            else
                bRet = true;
        }
        else if( aStart->bIsGrammarError )
            bRet = true;
        aStart++;
    }
    return bRet;
}
/*-- 10.09.2003 10:40:21---------------------------------------------------

  -----------------------------------------------------------------------*/
SentenceEditWindow_Impl::SentenceEditWindow_Impl( SpellDialog* pParent, const ResId& rResId ) :
    MultiLineEdit( pParent, rResId ),
    m_nErrorStart(0),
    m_nErrorEnd(0),
    m_bIsUndoEditMode(false)
{
    DisableSelectionOnFocus();
}
/*-- 10.09.2003 10:40:11---------------------------------------------------

  -----------------------------------------------------------------------*/
SentenceEditWindow_Impl::~SentenceEditWindow_Impl()
{
}
/*-- 20.10.2003 13:42:34---------------------------------------------------
    The selection before inputting a key may have a range or not
    and it may be inside or outside of field or error attributes.
    A range may include the attribute partially, completely or together
    with surrounding text. It may also contain more than one attribute
    or no attribute at all.
    Depending on this starting conditions some actions are necessary:
    Attempts to delete a field are only allowed if the selection is the same
    as the field's selection. Otherwise the field has to be selected and the key
    input action has to be skipped.
    Input of text at the start of the field requires the field attribute to be
    corrected - it is not allowed to grow.

    In case of errors the appending of text should grow the error attribute because
    that is what the user usually wants to do.

    Backspace at the start of the attribute requires to find out if a field ends
    directly in front of the cursor position. In case of a field this attribute has to be
    selected otherwise the key input method is allowed.

    All changes outside of the error attributes switch the dialog mode to a "Undo edit" state that
    removes all visible attributes and switches off further attribute checks.
    Undo in this restarts the dialog with a current sentence newly presented.
    All changes to the sentence are undone including the ones before the "Undo edit state" has been reached

    We end up with 9 types of selection
    1 (LEFT_NO)     - no range, start of attribute - can also be 3 at the same time
    2 (INSIDE_NO)   - no range, inside of attribute
    3 (RIGHT_NO)    - no range, end of attribute - can also be 1 at the same time
    4 (FULL)        - range, same as attribute
    5 (INSIDE_YES)  - range, inside of the attribute
    6 (BRACE)- range, from outside of the attribute to the inside or
                including the complete attribute and something outside,
                maybe more than one attribute
    7 (OUTSIDE_NO)  - no range, not at an attribute
    8 (OUTSIDE_YES) - range, completely outside of all attributes

    What has to be done depending on the attribute type involved
    possible actions:   UE - Undo edit mode
                        CO - Continue, no additional action is required
                        FS - Field has to be completely selected
                        EX - The attribute has to be expanded to include the added text

    1 - backspace                   delete                      any other
        UE                          on field FS on error CO     on field FS on error CO

    2 - on field FS on error C
    3 - backspace                   delete                      any other
        on field FS on error CO     UE                          on field UE on error EX

    if 1 and 3 happen to apply both then backspace and other handling is 1 delete is 3

    4 - on field UE and on error CO
    5 - on field FS and on error CO
    6 - on field FS and on error UE
    7 - UE
    8 - UE
  -----------------------------------------------------------------------*/
#define     INVALID     0
#define     LEFT_NO     1
#define     INSIDE_NO   2
#define     RIGHT_NO    3
#define     FULL        4
#define     INSIDE_YES  5
#define     BRACE       6
#define     OUTSIDE_NO  7
#define     OUTSIDE_YES 8

#define ACTION_UNDOEDIT    0
#define ACTION_CONTINUE    1
#define ACTION_SELECTFIELD 2
#define ACTION_EXPAND      3

long SentenceEditWindow_Impl::PreNotify( NotifyEvent& rNEvt )
{
    bool bChange = false;
    const TextCharAttrib*  pErrorAttrib = 0;
    if(rNEvt.GetType() == EVENT_KEYINPUT)
    {
        const KeyEvent& rKeyEvt = *rNEvt.GetKeyEvent();
        bChange = TextEngine::DoesKeyChangeText( rKeyEvt );
        if(bChange && !IsUndoEditMode() &&
            rKeyEvt.GetKeyCode().GetCode() != KEY_TAB)
        {
            TextEngine* pTextEngine = GetTextEngine();
            TextView* pTextView = pTextEngine->GetActiveView();
            const TextSelection& rCurrentSelection = pTextView->GetSelection();
            //determine if the selection contains a field
            bool bHasField = false;
            bool bHasError = false;
            bool bHasFieldLeft = false;
            bool bHasErrorLeft = false;
//            bool bInsideAttr = false;

            bool bHasRange = rCurrentSelection.HasRange();
            sal_uInt8 nSelectionType = 0; // invalid type!

            TextPaM aCursor(rCurrentSelection.GetStart());
            const TextCharAttrib* pBackAttr = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_BACKGROUND );
            const TextCharAttrib* pErrorAttr = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_ERROR );
            const TextCharAttrib* pBackAttrLeft = 0;
            const TextCharAttrib* pErrorAttrLeft = 0;

            bHasField = pBackAttr != 0 && (bHasRange || pBackAttr->GetEnd() > aCursor.GetIndex());
            bHasError = pErrorAttr != 0 && (bHasRange || pErrorAttr->GetEnd() > aCursor.GetIndex());
            if(bHasRange)
            {
                if(pBackAttr &&
                        pBackAttr->GetStart() == rCurrentSelection.GetStart().GetIndex() &&
                        pBackAttr->GetEnd() == rCurrentSelection.GetEnd().GetIndex())
                {
                    nSelectionType = FULL;
                }
                else if(pErrorAttr &&
                        pErrorAttr->GetStart() <= rCurrentSelection.GetStart().GetIndex() &&
                        pErrorAttr->GetEnd() >= rCurrentSelection.GetEnd().GetIndex())
                {
                    nSelectionType = INSIDE_YES;
                }
                else
                {
                    nSelectionType = bHasField||bHasError ? BRACE : OUTSIDE_NO;
                    while(aCursor.GetIndex() < rCurrentSelection.GetEnd().GetIndex())
                    {
                        ++aCursor.GetIndex();
                        const TextCharAttrib* pIntBackAttr = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_BACKGROUND );
                        const TextCharAttrib* pIntErrorAttr = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_ERROR );
                        //if any attr has been found then BRACE
                        if(pIntBackAttr || pIntErrorAttr)
                            nSelectionType = BRACE;
                        //the field has to be selected
                        if(pIntBackAttr && !pBackAttr)
                            pBackAttr = pIntBackAttr;
                        bHasField |= pIntBackAttr != 0;
                    }
                }
            }
            else
            {
                //no range selection: then 1 2 3 and 8 are possible
                const TextCharAttrib* pCurAttr = pBackAttr ? pBackAttr : pErrorAttr;
                if(pCurAttr)
                {
                    nSelectionType = pCurAttr->GetStart() == rCurrentSelection.GetStart().GetIndex() ?
                            LEFT_NO : pCurAttr->GetEnd() == rCurrentSelection.GetEnd().GetIndex() ? RIGHT_NO : INSIDE_NO;
                }
                else
                    nSelectionType = OUTSIDE_NO;

                bHasFieldLeft = pBackAttr && pBackAttr->GetEnd() == aCursor.GetIndex();
				if(bHasFieldLeft)
				{
					pBackAttrLeft = pBackAttr;
					pBackAttr = 0;
				}
                bHasErrorLeft = pErrorAttr && pErrorAttr->GetEnd() == aCursor.GetIndex();
				if(bHasErrorLeft)
				{
					pErrorAttrLeft = pErrorAttr;
					pErrorAttr = 0;
				}

                //check previous position if this exists
				//that is a redundant in the case the attribute found above already is on the left cursor side
				//but it's o.k. for two errors/fields side by side
                if(aCursor.GetIndex())
                {
                    --aCursor.GetIndex();
                    pBackAttrLeft = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_BACKGROUND );
                    pErrorAttrLeft = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_ERROR );
                    bHasFieldLeft = pBackAttrLeft !=0;
                    bHasErrorLeft = pErrorAttrLeft != 0;
//                    bInsideAttr = (bHasField || bHasError) && (bHasFieldLeft || bHasErrorLeft);
                    ++aCursor.GetIndex();
                }
            }
			//Here we have to determine if the error found is the one currently active
			bool bIsErrorActive = (pErrorAttr && pErrorAttr->GetStart() == m_nErrorStart) ||
					(pErrorAttrLeft && pErrorAttrLeft->GetStart() == m_nErrorStart);

            DBG_ASSERT(nSelectionType != INVALID, "selection type not set!");

            const KeyCode& rKeyCode = rKeyEvt.GetKeyCode();
            bool bDelete = rKeyCode.GetCode() == KEY_DELETE;
            bool bBackspace = rKeyCode.GetCode() == KEY_BACKSPACE;

            sal_Int8 nAction = ACTION_CONTINUE;
//            nAction = ACTION_UNDOEDIT
//            nAction = ACTION_SELECTFIELD
//            nAction = ACTION_EXPAND
            switch(nSelectionType)
            {
//    1 - backspace                   delete                      any other
//        UE                          on field FS on error CO     on field FS on error CO
                case LEFT_NO    :
                    if(bBackspace)
                    {
                        nAction = bHasFieldLeft ? ACTION_SELECTFIELD : ACTION_UNDOEDIT;
                        //to force the use of pBackAttrLeft
                        pBackAttr = 0;
                    }
                    else if(bDelete)
						nAction = bHasField ? ACTION_SELECTFIELD : ACTION_CONTINUE;
					else
						nAction = bHasError && !aCursor.GetIndex() ? ACTION_CONTINUE :
							bHasError ? ACTION_EXPAND : bHasErrorLeft ? ACTION_CONTINUE : ACTION_UNDOEDIT;
                break;
//    2 - on field FS on error C
                case INSIDE_NO  :
                    nAction =  bHasField ? ACTION_SELECTFIELD :
                        bIsErrorActive ? ACTION_CONTINUE : ACTION_UNDOEDIT;
                break;
//    3 - backspace                   delete                      any other
//        on field FS on error CO     UE                          on field UE on error EX
                case RIGHT_NO   :
                    if(bBackspace)
                        nAction = bHasFieldLeft ? ACTION_SELECTFIELD : ACTION_CONTINUE;
                    else if(bDelete)
						nAction = bHasFieldLeft && bHasError ? ACTION_CONTINUE : ACTION_UNDOEDIT;
					else
						nAction = bHasFieldLeft && bHasError ? ACTION_EXPAND :
							bHasError ? ACTION_CONTINUE : bHasErrorLeft ? ACTION_EXPAND :ACTION_UNDOEDIT;
                break;
//    4 - on field UE and on error CO
                case FULL       :
                    nAction = bHasField ? ACTION_UNDOEDIT : ACTION_CONTINUE;
                break;
//    5 - on field FS and on error CO
                case INSIDE_YES :
                    nAction = bHasField ? ACTION_SELECTFIELD : ACTION_CONTINUE;
                break;
//    6 - on field FS and on error UE
                case BRACE      :
                    nAction = bHasField ? ACTION_SELECTFIELD : ACTION_UNDOEDIT;
                break;
//    7 - UE
//    8 - UE
                case OUTSIDE_NO :
                case OUTSIDE_YES:
                    nAction = ACTION_UNDOEDIT;
                break;
            }
			//save the current paragraph
			sal_uInt16 nCurrentLen = GetText().Len();
            if(nAction != ACTION_SELECTFIELD)
                pTextView->GetWindow()->KeyInput(rKeyEvt);
            else
            {
                const TextCharAttrib* pCharAttr = pBackAttr ? pBackAttr : pBackAttrLeft;
                if(pCharAttr)
                {
                    TextPaM aStart(0, pCharAttr->GetStart());
                    TextPaM aEnd(0, pCharAttr->GetEnd());
                    TextSelection aNewSel(aStart, aEnd);
                    pTextView->SetSelection( aNewSel);
                }
            }
            if(nAction == ACTION_EXPAND)
            {
                DBG_ASSERT(pErrorAttrLeft || pErrorAttr, "where is the error");
                //text has been added on the right and only the 'error attribute has to be corrected
				if(pErrorAttrLeft)
                {
                    TextAttrib* pNewError =  pErrorAttrLeft->GetAttr().Clone();
                    sal_uInt16 nStart = pErrorAttrLeft->GetStart();
                    sal_uInt16 nEnd = pErrorAttrLeft->GetEnd();
                    pTextEngine->RemoveAttrib( 0, *pErrorAttrLeft );
                    SetAttrib( *pNewError, 0, nStart, ++nEnd );
                    //only active errors move the mark
					if(bIsErrorActive)
                    {
                        bool bGrammar = static_cast<const SpellErrorAttrib&>(*pNewError).GetErrorDescription().bIsGrammarError;
                        MoveErrorMarkTo(nStart, nEnd, bGrammar);
                    }
                    delete pNewError;
                }
				//text has been added on the left then the error attribute has to be expanded and the
				//field attribute on the right - if any - has to be contracted
				else if(pErrorAttr)
				{
					//determine the change
					sal_uInt16 nAddedChars = GetText().Len() - nCurrentLen;

                    TextAttrib* pNewError =  pErrorAttr->GetAttr().Clone();
                    sal_uInt16 nStart = pErrorAttr->GetStart();
                    sal_uInt16 nEnd = pErrorAttr->GetEnd();
                    pTextEngine->RemoveAttrib( 0, *pErrorAttr );
                    nStart = nStart - (sal_uInt16)nAddedChars;
					SetAttrib( *pNewError, 0, nStart - nAddedChars, nEnd );
                    //only if the error is active the mark is moved here
					if(bIsErrorActive)
                    {
                        bool bGrammar = static_cast<const SpellErrorAttrib&>(*pNewError).GetErrorDescription().bIsGrammarError;
                        MoveErrorMarkTo(nStart, nEnd, bGrammar);
                    }
                    delete pNewError;

					if(pBackAttrLeft)
					{
						TextAttrib* pNewBack =  pBackAttrLeft->GetAttr().Clone();
                        sal_uInt16 _nStart = pBackAttrLeft->GetStart();
                        sal_uInt16 _nEnd = pBackAttrLeft->GetEnd();
						pTextEngine->RemoveAttrib( 0, *pBackAttrLeft );
                        SetAttrib( *pNewBack, 0, _nStart, _nEnd - nAddedChars);
						delete pNewBack;
					}
				}
            }
            else if(nAction == ACTION_UNDOEDIT)
            {
                SetUndoEditMode(true);
            }
            //make sure the error positions are correct after text changes
            //the old attribute may have been deleted
            //all changes inside of the current error leave the error attribute at the current
            //start position
            if(!IsUndoEditMode() && bIsErrorActive)
            {
                const TextCharAttrib* pFontColor = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_FONTCOLOR );
                pErrorAttrib = pTextEngine->FindCharAttrib( TextPaM(0, m_nErrorStart), TEXTATTR_SPELL_ERROR );
                if(pFontColor && pErrorAttrib )
                {
                    m_nErrorStart = pFontColor->GetStart();
                    m_nErrorEnd = pFontColor->GetEnd();
                    if(pErrorAttrib->GetStart() != m_nErrorStart || pErrorAttrib->GetEnd() != m_nErrorEnd)
                    {
                        TextAttrib* pNewError =  pErrorAttrib->GetAttr().Clone();
                        pTextEngine->RemoveAttrib( 0, *pErrorAttr );
                        SetAttrib( *pNewError, 0, m_nErrorStart, m_nErrorEnd );
                        delete pNewError;
                    }
                }
            }
            //this is not a modification anymore
			if(nAction != ACTION_SELECTFIELD && !m_bIsUndoEditMode)
				CallModifyLink();
        }
		else
			bChange = false;
    }
    long nRet = bChange ? 1 : MultiLineEdit::PreNotify(rNEvt);
    return nRet;
}
/*-- 10.09.2003 13:38:14---------------------------------------------------

  -----------------------------------------------------------------------*/
bool SentenceEditWindow_Impl::MarkNextError( bool bIgnoreCurrentError )
{
    if (bIgnoreCurrentError)
        m_aIgnoreErrorsAt.insert( m_nErrorStart );
    ExtTextEngine* pTextEngine = GetTextEngine();
    sal_uInt16 nTextLen = pTextEngine->GetTextLen(0);
    if(m_nErrorEnd >= nTextLen - 1)
        return false;
	//if it's not already modified the modified flag has to be reset at the and of the marking
    bool bModified = IsModified();
    bool bRet = false;
    const sal_uInt16 nOldErrorStart = m_nErrorStart;
    const sal_uInt16 nOldErrorEnd   = m_nErrorEnd;

    //create a cursor behind the end of the last error
	//- or at 0 at the start of the sentence
    TextPaM aCursor(0, m_nErrorEnd ? m_nErrorEnd + 1 : 0);
    //search for SpellErrorAttrib

    const TextCharAttrib* pNextError = 0;
    //iterate over the text and search for the next error that maybe has
    //to be replace by a ChangeAllList replacement
    bool bGrammarError = false;
    while(aCursor.GetIndex() < nTextLen)
    {
        while(aCursor.GetIndex() < nTextLen &&
                0 == (pNextError = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_ERROR)))
        {
            ++aCursor.GetIndex();
        }
        // maybe the error found here is already in the ChangeAllList and has to be replaced

        Reference<XDictionary> xChangeAll( SvxGetChangeAllList(), UNO_QUERY );
        Reference<XDictionaryEntry> xEntry;

//        Reference <XSpellAlternatives> xAlternatives;
        const SpellErrorDescription* pSpellErrorDescription = 0;
        if(pNextError)
        {
            pSpellErrorDescription = &static_cast<const SpellErrorAttrib&>(pNextError->GetAttr()).GetErrorDescription();
            bGrammarError = pSpellErrorDescription->bIsGrammarError;
        }
        if(xChangeAll->getCount() && pSpellErrorDescription &&
                (xEntry = xChangeAll->getEntry( pSpellErrorDescription->sErrorText )).is())
        {
            m_nErrorStart = pNextError->GetStart();
            m_nErrorEnd = pNextError->GetEnd();
            ChangeMarkedWord(xEntry->getReplacementText(),
                    SvxLocaleToLanguage( pSpellErrorDescription->aLocale ));
            aCursor.GetIndex() = aCursor.GetIndex() + (sal_uInt16)(xEntry->getReplacementText().getLength());
        }
		else
			break;
    }

    //if an attrib has been found search for the end of the error string
    if(aCursor.GetIndex() < nTextLen)
    {
        m_nErrorStart = aCursor.GetIndex();
        m_nErrorEnd = pNextError->GetEnd();
        MoveErrorMarkTo(m_nErrorStart, m_nErrorEnd, bGrammarError);
        bRet = true;
		//add an undo action
        SpellUndoAction_Impl* pAction = new SpellUndoAction_Impl(
                SPELLUNDO_CHANGE_NEXTERROR, GetSpellDialog()->aDialogUndoLink);
        pAction->SetErrorMove(m_nErrorStart, m_nErrorEnd, nOldErrorStart, nOldErrorEnd);
        const SpellErrorAttrib* pOldAttrib = static_cast<const SpellErrorAttrib*>(
                pTextEngine->FindAttrib( TextPaM(0, nOldErrorStart), TEXTATTR_SPELL_ERROR ));
        pAction->SetErrorLanguageSelected(pOldAttrib && pOldAttrib->GetErrorDescription().aSuggestions.getLength() &&
                SvxLocaleToLanguage( pOldAttrib->GetErrorDescription().aLocale) ==
                                        GetSpellDialog()->aLanguageLB.GetSelectLanguage());
        AddUndoAction(pAction);
    }
    else
        m_nErrorStart = m_nErrorEnd = nTextLen;
    if( !bModified )
        ClearModifyFlag();
    SpellDialog* pSpellDialog = GetSpellDialog();
    pSpellDialog->aIgnorePB.Enable(bRet);
    pSpellDialog->aIgnoreAllPB.Enable(bRet);
    pSpellDialog->aAutoCorrPB.Enable(bRet);
    pSpellDialog->aAddToDictMB.Enable(bRet);
	return bRet;
}

/*-- 06.11.2003 13:30:26---------------------------------------------------

  -----------------------------------------------------------------------*/
void SentenceEditWindow_Impl::MoveErrorMarkTo(sal_uInt16 nStart, sal_uInt16 nEnd, bool bGrammarError)
{
    TextEngine* pTextEngine = GetTextEngine();
    pTextEngine->RemoveAttribs( 0, (sal_uInt16)TEXTATTR_FONTCOLOR, sal_True );
    pTextEngine->RemoveAttribs( 0, (sal_uInt16)TEXTATTR_FONTWEIGHT, sal_True );
    pTextEngine->SetAttrib( TextAttribFontWeight(WEIGHT_BOLD), 0, nStart, nEnd );
    pTextEngine->SetAttrib( TextAttribFontColor(bGrammarError ? COL_LIGHTBLUE : COL_LIGHTRED), 0, nStart, nEnd );
    m_nErrorStart = nStart;
    m_nErrorEnd = nEnd;
}

/*-- 17.09.2003 10:13:08---------------------------------------------------

  -----------------------------------------------------------------------*/
void SentenceEditWindow_Impl::ChangeMarkedWord(const String& rNewWord, LanguageType eLanguage)
{
    //calculate length changes
    long nDiffLen = rNewWord.Len() - m_nErrorEnd + m_nErrorStart;
    TextSelection aSel(TextPaM(0, m_nErrorStart), TextPaM(0, m_nErrorEnd));
    //Remove spell error attribute
    ExtTextEngine* pTextEngine = GetTextEngine();
    pTextEngine->UndoActionStart();
    const TextCharAttrib*  pErrorAttrib = pTextEngine->FindCharAttrib( TextPaM(0, m_nErrorStart), TEXTATTR_SPELL_ERROR );
    DBG_ASSERT(pErrorAttrib, "no error attribute found");
//  Reference <XSpellAlternatives> xAlternatives;
    const SpellErrorDescription* pSpellErrorDescription = 0;
    if(pErrorAttrib)
	{
        pTextEngine->RemoveAttrib(0, *pErrorAttrib);
        pSpellErrorDescription = &static_cast<const SpellErrorAttrib&>(pErrorAttrib->GetAttr()).GetErrorDescription();
	}
    const TextCharAttrib*  pBackAttrib = pTextEngine->FindCharAttrib( TextPaM(0, m_nErrorStart), TEXTATTR_SPELL_BACKGROUND );
    pTextEngine->ReplaceText( aSel, rNewWord );
    //
    if(!m_nErrorStart)
    {
        //attributes following an error at the start of the text are not moved but expanded from the
        //text engine - this is done to keep full-paragraph-attributes
        //in the current case that handling is not desired
        const TextCharAttrib*  pLangAttrib =
                pTextEngine->FindCharAttrib(
                    TextPaM(0, m_nErrorEnd), TEXTATTR_SPELL_LANGUAGE );
        sal_uInt16 nTextLen = pTextEngine->GetTextLen( 0 );
        if(pLangAttrib && !pLangAttrib->GetStart() && pLangAttrib->GetEnd() ==
            nTextLen)
        {
            SpellLanguageAttrib aNewLangAttrib( static_cast<const SpellLanguageAttrib&>(pLangAttrib->GetAttr()).GetLanguage());
            pTextEngine->RemoveAttrib(0, *pLangAttrib);
            pTextEngine->SetAttrib( aNewLangAttrib, 0, (sal_uInt16)(m_nErrorEnd + nDiffLen) , nTextLen );
        }
    }
	// undo expanded attributes!
	if( pBackAttrib && pBackAttrib->GetStart() < m_nErrorStart && pBackAttrib->GetEnd() == m_nErrorEnd + nDiffLen)
	{
		TextAttrib* pNewBackground = pBackAttrib->GetAttr().Clone();
        sal_uInt16 nStart = pBackAttrib->GetStart();
		pTextEngine->RemoveAttrib(0, *pBackAttrib);
		pTextEngine->SetAttrib(*pNewBackground, 0, nStart, m_nErrorStart);
		delete pNewBackground;
	}
    pTextEngine->SetModified(sal_True);

    //adjust end position
    long nEndTemp = m_nErrorEnd;
    nEndTemp += nDiffLen;
    m_nErrorEnd = (sal_uInt16)nEndTemp;

    SpellUndoAction_Impl* pAction = new SpellUndoAction_Impl(
                    SPELLUNDO_MOVE_ERROREND, GetSpellDialog()->aDialogUndoLink);
    pAction->SetOffset(nDiffLen);
    AddUndoAction(pAction);
    if(pSpellErrorDescription)
        SetAttrib( SpellErrorAttrib(*pSpellErrorDescription), 0, m_nErrorStart, m_nErrorEnd );
    SetAttrib( SpellLanguageAttrib(eLanguage), 0, m_nErrorStart, m_nErrorEnd );
    pTextEngine->UndoActionEnd();
}
/* -----------------08.10.2003 13:18-----------------

 --------------------------------------------------*/
String SentenceEditWindow_Impl::GetErrorText() const
{
    return GetTextEngine()->GetText(TextSelection(TextPaM(0, m_nErrorStart), TextPaM(0, m_nErrorEnd) ));
}
/*-- 26.06.2008 10:54:13---------------------------------------------------

  -----------------------------------------------------------------------*/
const SpellErrorDescription* SentenceEditWindow_Impl::GetAlternatives()
{
    TextPaM aCursor(0, m_nErrorStart);
    const SpellErrorAttrib* pAttrib = static_cast<const SpellErrorAttrib*>(
            GetTextEngine()->FindAttrib( aCursor, TEXTATTR_SPELL_ERROR));
    return pAttrib ? &pAttrib->GetErrorDescription() : 0;
}
/*-- 06.09.2004 10:50:32---------------------------------------------------

  -----------------------------------------------------------------------*/
void SentenceEditWindow_Impl::RestoreCurrentError()
{
    TextPaM aCursor(0, m_nErrorStart);
    const SpellErrorAttrib* pAttrib = static_cast<const SpellErrorAttrib*>(
            GetTextEngine()->FindAttrib( aCursor, TEXTATTR_SPELL_ERROR));
    if( pAttrib )
    {
        const SpellErrorDescription& rDesc = pAttrib->GetErrorDescription();
        if( !rDesc.sErrorText.equals( GetErrorText() ) )
            ChangeMarkedWord(rDesc.sErrorText, SvxLocaleToLanguage( rDesc.aLocale ));
    }
}
/*-- 28.10.2003 14:44:10---------------------------------------------------

  -----------------------------------------------------------------------*/
void SentenceEditWindow_Impl::SetAlternatives( Reference< XSpellAlternatives> xAlt )
{
    TextPaM aCursor(0, m_nErrorStart);
    DBG_ASSERT(static_cast<const SpellErrorAttrib*>(
            GetTextEngine()->FindAttrib( aCursor, TEXTATTR_SPELL_ERROR)), "no error set?");

	::rtl::OUString	aWord;
	lang::Locale	aLocale;
	uno::Sequence< ::rtl::OUString >	aAlts;
	::rtl::OUString sServiceName;
	if (xAlt.is())
	{
		aWord	= xAlt->getWord();
		aLocale	= xAlt->getLocale();
		aAlts	= xAlt->getAlternatives();
		uno::Reference< container::XNamed > xNamed( xAlt, uno::UNO_QUERY );
		if (xNamed.is())
			sServiceName = xNamed->getName();
	}
	SpellErrorDescription aDesc( false, aWord, aLocale, aAlts, 0, sServiceName);
	GetTextEngine()->SetAttrib( SpellErrorAttrib(aDesc), 0, m_nErrorStart, m_nErrorEnd );
}

/*-- 10.09.2003 14:43:02---------------------------------------------------

  -----------------------------------------------------------------------*/
void SentenceEditWindow_Impl::SetAttrib( const TextAttrib& rAttr, sal_uLong nPara, sal_uInt16 nStart, sal_uInt16 nEnd )
{
	GetTextEngine()->SetAttrib(rAttr, nPara, nStart, nEnd);
}
/*-- 10.09.2003 14:43:02---------------------------------------------------

  -----------------------------------------------------------------------*/
void SentenceEditWindow_Impl::SetText( const String& rStr )
{
	m_nErrorStart = m_nErrorEnd = 0;
	GetTextEngine()->SetText(rStr);
//	InitScrollBars();
}
/*-- 08.10.2003 14:35:52---------------------------------------------------

  -----------------------------------------------------------------------*/
struct LanguagePosition_Impl
{
    sal_uInt16          nPosition;
    LanguageType    eLanguage;

    LanguagePosition_Impl(sal_uInt16 nPos, LanguageType eLang) :
        nPosition(nPos),
        eLanguage(eLang)
        {}
};
typedef std::vector<LanguagePosition_Impl> LanguagePositions_Impl;

void lcl_InsertBreakPosition_Impl(
		LanguagePositions_Impl& rBreakPositions, sal_uInt16 nInsert, LanguageType eLanguage)
{
	LanguagePositions_Impl::iterator aStart = rBreakPositions.begin();
	while(aStart != rBreakPositions.end())
	{
		if(aStart->nPosition == nInsert)
		{
			// the language of following starts has to overwrite
			// the one of previous ends
			aStart->eLanguage = eLanguage;
			return;
		}
		else if(aStart->nPosition > nInsert)
		{

            rBreakPositions.insert(aStart, LanguagePosition_Impl(nInsert, eLanguage));
            return;
        }
        else
            ++aStart;
    }
    rBreakPositions.push_back(LanguagePosition_Impl(nInsert, eLanguage));
}
/*-- 17.09.2003 14:26:59---------------------------------------------------
    Returns the text in spell portions. Each portion contains text with an
    equal language and attribute. The spell alternatives are empty.
  -----------------------------------------------------------------------*/
svx::SpellPortions SentenceEditWindow_Impl::CreateSpellPortions( bool bSetIgnoreFlag ) const
{
    svx::SpellPortions aRet;
    ExtTextEngine* pTextEngine = GetTextEngine();
    const sal_uInt16 nTextLen = pTextEngine->GetTextLen(0);
    if(nTextLen)
    {
        TextPaM aCursor(0, 0);
        LanguagePositions_Impl aBreakPositions;
        const TextCharAttrib* pLastLang = 0;
        const TextCharAttrib* pLastError = 0;
        LanguageType eLang = LANGUAGE_DONTKNOW;
		const TextCharAttrib* pError = 0;
        while(aCursor.GetIndex() < nTextLen)
        {
            const TextCharAttrib* pLang = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_LANGUAGE);
            if(pLang && pLang != pLastLang)
            {
                eLang = static_cast<const SpellLanguageAttrib&>(pLang->GetAttr()).GetLanguage();
                lcl_InsertBreakPosition_Impl(aBreakPositions, pLang->GetStart(), eLang);
                lcl_InsertBreakPosition_Impl(aBreakPositions, pLang->GetEnd(), eLang);
                pLastLang = pLang;
            }
            pError = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_ERROR);
            if(pError && pLastError != pError)
            {
                lcl_InsertBreakPosition_Impl(aBreakPositions, pError->GetStart(), eLang);
                lcl_InsertBreakPosition_Impl(aBreakPositions, pError->GetEnd(), eLang);
                pLastError = pError;

            }
            aCursor.GetIndex()++;
        }
        //
        if(nTextLen && aBreakPositions.empty())
        {
            //if all content has been overwritten the attributes may have been removed, too
            svx::SpellPortion aPortion1;
            aPortion1.eLanguage = GetSpellDialog()->GetSelectedLang_Impl();
            aPortion1.sText = pTextEngine->GetText(
                        TextSelection(TextPaM(0, 0), TextPaM(0, nTextLen)));

            aRet.push_back(aPortion1);

        }
        else if(!aBreakPositions.empty())
        {
            LanguagePositions_Impl::iterator aStart = aBreakPositions.begin();
            //start should always be Null
            eLang = aStart->eLanguage;
            sal_uInt16 nStart = aStart->nPosition;
            DBG_ASSERT(!nStart, "invalid start position - language attribute missing?");
            ++aStart;

            while(aStart != aBreakPositions.end())
            {
                svx::SpellPortion aPortion1;
                aPortion1.eLanguage = eLang;
                aPortion1.sText = pTextEngine->GetText(
                            TextSelection(TextPaM(0, nStart), TextPaM(0, aStart->nPosition)));
                bool bIsIgnoreError = m_aIgnoreErrorsAt.find( nStart ) != m_aIgnoreErrorsAt.end();
                if( bSetIgnoreFlag && bIsIgnoreError /*m_nErrorStart == nStart*/ )
                {
                    aPortion1.bIgnoreThisError = true;
                }
                aRet.push_back(aPortion1);
                nStart = aStart->nPosition;
                eLang = aStart->eLanguage;
                ++aStart;
            }
		}

		// quick partly fix of #i71318. Correct fix needs to patch the TextEngine itself...
		// this one will only prevent text from disappearing. It may to not have the
		// correct language and will probably not spell checked...
		sal_uLong nPara = pTextEngine->GetParagraphCount();
		if (nPara > 1)
		{
			String aLeftOverText;
			for (sal_uLong i = 1;  i < nPara;  ++i)
			{
				aLeftOverText.AppendAscii( "\x0a" );	// the manual line break...
				aLeftOverText += pTextEngine->GetText(i);
			}
			if (pError)
			{	// we need to add a new portion containing the left-over text
				svx::SpellPortion aPortion2;
				aPortion2.eLanguage = eLang;
				aPortion2.sText = aLeftOverText;
				aRet.push_back( aPortion2 );
			}
			else
			{	// we just need to append the left-over text to the last portion (which had no errors)
				aRet[ aRet.size() - 1 ].sText += aLeftOverText;
			}
		}
	}
	return aRet;
}

/*-- 06.11.2003 11:30:10---------------------------------------------------

  -----------------------------------------------------------------------*/
void SentenceEditWindow_Impl::Undo()
{
    ::svl::IUndoManager& rUndoMgr = GetTextEngine()->GetUndoManager();
    DBG_ASSERT(GetUndoActionCount(), "no undo actions available" );
    if(!GetUndoActionCount())
        return;
    bool bSaveUndoEdit = IsUndoEditMode();
    sal_uInt16 nId;
    // if the undo edit mode is active then undo all changes until the UNDO_EDIT_MODE action has been found
    do
    {
        nId = rUndoMgr.GetUndoActionId();
        rUndoMgr.Undo();
    }while(bSaveUndoEdit && SPELLUNDO_UNDO_EDIT_MODE != nId && GetUndoActionCount());

	if(bSaveUndoEdit || SPELLUNDO_CHANGE_GROUP == nId)
		GetSpellDialog()->UpdateBoxes_Impl();
}
/*-- 06.11.2003 11:30:10---------------------------------------------------

  -----------------------------------------------------------------------*/
void SentenceEditWindow_Impl::ResetUndo()
{
	GetTextEngine()->ResetUndo();
}
/*-- 06.11.2003 12:30:41---------------------------------------------------

  -----------------------------------------------------------------------*/
void SentenceEditWindow_Impl::AddUndoAction( SfxUndoAction *pAction, sal_Bool bTryMerg )
{
	::svl::IUndoManager& rUndoMgr = GetTextEngine()->GetUndoManager();
	rUndoMgr.AddUndoAction(pAction, bTryMerg);
	GetSpellDialog()->aUndoPB.Enable();
}
/*-- 06.11.2003 12:38:44---------------------------------------------------

  -----------------------------------------------------------------------*/
sal_uInt16 SentenceEditWindow_Impl::GetUndoActionCount()
{
	return GetTextEngine()->GetUndoManager().GetUndoActionCount();
}

/*-- 12.11.2003 12:12:38---------------------------------------------------

  -----------------------------------------------------------------------*/
void SentenceEditWindow_Impl::UndoActionStart( sal_uInt16 nId )
{
	GetTextEngine()->UndoActionStart(nId);
}
/*-- 12.11.2003 12:12:38---------------------------------------------------

  -----------------------------------------------------------------------*/
void SentenceEditWindow_Impl::UndoActionEnd()
{
	GetTextEngine()->UndoActionEnd();
}
/*-- 12.11.2003 12:12:38---------------------------------------------------

  -----------------------------------------------------------------------*/
void SentenceEditWindow_Impl::MoveErrorEnd(long nOffset)
{
	if(nOffset > 0)
		m_nErrorEnd = m_nErrorEnd - (sal_uInt16)nOffset;
	else
		m_nErrorEnd = m_nErrorEnd -(sal_uInt16)- nOffset;
}
/*-- 13.11.2003 15:15:19---------------------------------------------------

  -----------------------------------------------------------------------*/
void  SentenceEditWindow_Impl::SetUndoEditMode(bool bSet)
{
    DBG_ASSERT(!bSet || m_bIsUndoEditMode != bSet, "SetUndoEditMode with equal values?");
    m_bIsUndoEditMode = bSet;
    // disable all buttons except the Change
    SpellDialog* pSpellDialog = GetSpellDialog();
    Control* aControls[] =
    {
        &pSpellDialog->aChangeAllPB,
        &pSpellDialog->aExplainPB,
        &pSpellDialog->aIgnoreAllPB,
        &pSpellDialog->aIgnoreRulePB,
        &pSpellDialog->aIgnorePB,
        &pSpellDialog->aSuggestionLB,
        &pSpellDialog->aSuggestionFT,
        &pSpellDialog->aLanguageFT,
        &pSpellDialog->aLanguageLB,
        &pSpellDialog->aAddToDictMB,
        &pSpellDialog->aAutoCorrPB,
        0
    };
    sal_Int32 nIdx = 0;
    do
    {
        aControls[nIdx]->Enable(sal_False);
    }
    while(aControls[++nIdx]);

	// remove error marks
	TextEngine* pTextEngine = GetTextEngine();
	pTextEngine->RemoveAttribs( 0, (sal_uInt16)TEXTATTR_FONTCOLOR, sal_True );
	pTextEngine->RemoveAttribs( 0, (sal_uInt16)TEXTATTR_FONTWEIGHT, sal_True );

	// put the appropriate action on the Undo-stack
	SpellUndoAction_Impl* pAction = new SpellUndoAction_Impl(
						SPELLUNDO_UNDO_EDIT_MODE, GetSpellDialog()->aDialogUndoLink);
	AddUndoAction(pAction);
	pSpellDialog->aChangePB.Enable();
}

/*-- 30.06.2008 14:15:19---------------------------------------------------

  -----------------------------------------------------------------------*/
ExplainButton::~ExplainButton()
{
}
/*-- 30.06.2008 14:15:19---------------------------------------------------

  -----------------------------------------------------------------------*/
void ExplainButton::RequestHelp( const HelpEvent& )
{
	Help::ShowBalloon( this, GetPosPixel(), m_sExplanation );
}

void ExplainButton::Click()
{
	RequestHelp( HelpEvent() );
}

/* vim: set noet sw=4 ts=4: */
