LCOV - code coverage report
Current view: top level - libreoffice/cui/source/dialogs - SpellDialog.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1 1090 0.1 %
Date: 2012-12-17 Functions: 2 103 1.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <tools/shl.hxx>
      21             : #include <vcl/wrkwin.hxx>
      22             : #include <vcl/menu.hxx>
      23             : #include <vcl/msgbox.hxx>
      24             : #include <vcl/scrbar.hxx>
      25             : #include <SpellAttrib.hxx>
      26             : #include <sfx2/dispatch.hxx>
      27             : #include <sfx2/bindings.hxx>
      28             : #include <svl/undo.hxx>
      29             : #include <unotools/lingucfg.hxx>
      30             : #include <vcl/textdata.hxx>
      31             : #include <svtools/filter.hxx>
      32             : #include <editeng/unolingu.hxx>
      33             : #include <editeng/splwrap.hxx>
      34             : #include <linguistic/lngprops.hxx>
      35             : #include <linguistic/misc.hxx>
      36             : #include <comphelper/processfactory.hxx>
      37             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      38             : #include <com/sun/star/lang/XServiceInfo.hpp>
      39             : #include <com/sun/star/lang/XServiceDisplayName.hpp>
      40             : #include <com/sun/star/linguistic2/SpellFailure.hpp>
      41             : #include <com/sun/star/frame/XStorable.hpp>
      42             : #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
      43             : #include <com/sun/star/system/SystemShellExecute.hpp>
      44             : #include <sfx2/app.hxx>
      45             : #include <vcl/help.hxx>
      46             : #include <vcl/graph.hxx>
      47             : #include <osl/file.hxx>
      48             : #include <cuires.hrc>
      49             : #include <helpid.hrc>
      50             : #include "SpellDialog.hrc"
      51             : #include <editeng/optitems.hxx>
      52             : #include <editeng/svxenum.hxx>
      53             : #include <svx/SpellDialogChildWindow.hxx>
      54             : #include "SpellDialog.hxx"
      55             : #include <svx/dlgutil.hxx>
      56             : #include "optlingu.hxx"
      57             : #include <dialmgr.hxx>
      58             : #include <svx/svxerr.hxx>
      59             : #include "treeopt.hxx"
      60             : #include <svtools/langtab.hxx>
      61             : #include <comphelper/anytostring.hxx>
      62             : #include <cppuhelper/exc_hlp.hxx>
      63             : 
      64             : using namespace ::com::sun::star;
      65             : using namespace ::com::sun::star::uno;
      66             : using namespace ::com::sun::star::beans;
      67             : using namespace ::com::sun::star::linguistic2;
      68             : 
      69             : using ::rtl::OUString;
      70             : 
      71             : // struct SpellDialog_Impl ---------------------------------------------
      72             : 
      73           0 : struct SpellDialog_Impl
      74             : {
      75             :     Sequence< Reference< XDictionary >  >   aDics;
      76             : };
      77             : // -----------------------------------------------------------------------
      78             : 
      79             : #define SPELLUNDO_START                     200
      80             : 
      81             : #define SPELLUNDO_CHANGE_LANGUAGE           (SPELLUNDO_START + 1)
      82             : #define SPELLUNDO_CHANGE_TEXTENGINE         (SPELLUNDO_START + 2)
      83             : #define SPELLUNDO_CHANGE_NEXTERROR          (SPELLUNDO_START + 3)
      84             : #define SPELLUNDO_CHANGE_ADD_TO_DICTIONARY  (SPELLUNDO_START + 4)
      85             : #define SPELLUNDO_CHANGE_GROUP              (SPELLUNDO_START + 5) //undo list
      86             : #define SPELLUNDO_MOVE_ERROREND             (SPELLUNDO_START + 6)
      87             : #define SPELLUNDO_UNDO_EDIT_MODE            (SPELLUNDO_START + 7)
      88             : #define SPELLUNDO_ADD_IGNORE_RULE           (SPELLUNDO_START + 8)
      89             : 
      90             : namespace svx{
      91             : class SpellUndoAction_Impl : public SfxUndoAction
      92             : {
      93             :     sal_uInt16          m_nId;
      94             :     const Link&     m_rActionLink;
      95             :     //undo of button enabling
      96             :     bool            m_bEnableChangePB;
      97             :     bool            m_bEnableChangeAllPB;
      98             :     //undo of MarkNextError - used in change and change all, ignore and ignore all
      99             :     long            m_nNewErrorStart;
     100             :     long            m_nNewErrorEnd;
     101             :     long            m_nOldErrorStart;
     102             :     long            m_nOldErrorEnd;
     103             :     bool            m_bIsErrorLanguageSelected;
     104             :     ::rtl::OUString m_sRuleId;
     105             :     //undo of AddToDictionary
     106             :     Reference<XDictionary>  m_xDictionary;
     107             :     ::rtl::OUString                m_sAddedWord;
     108             :     //move end of error - ::ChangeMarkedWord()
     109             :     long            m_nOffset;
     110             : 
     111             : public:
     112           0 :     SpellUndoAction_Impl(sal_uInt16 nId, const Link& rActionLink) :
     113             :         m_nId(nId),
     114             :         m_rActionLink( rActionLink),
     115             :         m_bEnableChangePB(false),
     116             :         m_bEnableChangeAllPB(false),
     117             :         m_nNewErrorStart(-1),
     118             :         m_nNewErrorEnd(-1),
     119             :         m_nOldErrorStart(-1),
     120             :         m_nOldErrorEnd(-1),
     121             :         m_bIsErrorLanguageSelected(false),
     122           0 :         m_nOffset(0)
     123           0 :         {}
     124             : 
     125             :     ~SpellUndoAction_Impl();
     126             : 
     127             :     virtual void            Undo();
     128             :     virtual sal_uInt16          GetId() const;
     129             : 
     130           0 :     void                    SetEnableChangePB(){m_bEnableChangePB = true;}
     131           0 :     bool                    IsEnableChangePB(){return m_bEnableChangePB;}
     132             : 
     133           0 :     void                    SetEnableChangeAllPB(){m_bEnableChangeAllPB = true;}
     134           0 :     bool                    IsEnableChangeAllPB(){return m_bEnableChangeAllPB;}
     135             : 
     136           0 :     void                    SetErrorMove(long nNewStart, long nNewEnd, long nOldStart, long nOldEnd)
     137             :                                 {
     138           0 :                                         m_nNewErrorStart = nNewStart;
     139           0 :                                         m_nNewErrorEnd  = nNewEnd;
     140           0 :                                         m_nOldErrorStart = nOldStart;
     141           0 :                                         m_nOldErrorEnd = nOldEnd;
     142           0 :                                 }
     143             :     long                    GetNewErrorStart() { return m_nNewErrorStart;}
     144             :     long                    GetNewErrorEnd() { return m_nNewErrorEnd;}
     145           0 :     long                    GetOldErrorStart() { return m_nOldErrorStart;}
     146           0 :     long                    GetOldErrorEnd() { return m_nOldErrorEnd;}
     147             : 
     148           0 :     void                    SetErrorLanguageSelected(bool bSet){ m_bIsErrorLanguageSelected = bSet;}
     149           0 :     bool                    IsErrorLanguageSelected() const {return m_bIsErrorLanguageSelected;}
     150             : 
     151           0 :     void                    SetDictionary(Reference<XDictionary> xDict) { m_xDictionary = xDict; }
     152           0 :     Reference<XDictionary>  GetDictionary() const {return m_xDictionary;}
     153           0 :     void                    SetAddedWord(const ::rtl::OUString& rWord) {m_sAddedWord = rWord;}
     154           0 :     const ::rtl::OUString&         GetAddedWord() const { return m_sAddedWord;}
     155             : 
     156           0 :     void                    SetOffset(long nSet) {m_nOffset = nSet;}
     157           0 :     long                    GetOffset() const {return m_nOffset;}
     158             : 
     159             :     void                    SetErrorType( const ::rtl::OUString& rId ) { m_sRuleId = rId; }
     160             :     const ::rtl::OUString&  GetErrorType() const { return m_sRuleId; }
     161             : 
     162             : };
     163             : }//namespace svx
     164             : using namespace ::svx;
     165             : 
     166             : //-----------------------------------------------------------------------
     167           0 : SpellUndoAction_Impl::~SpellUndoAction_Impl()
     168             : {
     169           0 : }
     170             : 
     171             : //-----------------------------------------------------------------------
     172           0 : void SpellUndoAction_Impl::Undo()
     173             : {
     174           0 :     m_rActionLink.Call(this);
     175           0 : }
     176             : 
     177             : //-----------------------------------------------------------------------
     178           0 : sal_uInt16 SpellUndoAction_Impl::GetId()const
     179             : {
     180           0 :     return m_nId;
     181             : }
     182             : 
     183           0 : HelpFixedText::HelpFixedText( Window* pParent, const ResId& rResId ):
     184           0 :             FixedText( pParent, rResId )
     185             : {
     186           0 : }
     187             : 
     188           0 : void HelpFixedText::Paint( const Rectangle& rRect )
     189             : {
     190           0 :     Rectangle aTextRect( rRect.Left() + 6, rRect.Top(), rRect.Right() - 6, rRect.Bottom() );
     191           0 :     DrawText( aTextRect, GetText(), TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE );
     192           0 : }
     193             : 
     194           0 : long HelpFixedText::GetActualHeight( )
     195             : {
     196           0 :     Rectangle rRect( GetPosPixel( ), GetSizePixel() );
     197           0 :     Rectangle aTextRect( rRect.Left() + 6, rRect.Top(), rRect.Right() - 6, rRect.Bottom() );
     198           0 :     Rectangle aBounds = GetTextRect( aTextRect, GetText(), TEXT_DRAW_WORDBREAK | TEXT_DRAW_MULTILINE );
     199             : 
     200           0 :     return aBounds.getHeight();
     201             : }
     202             : 
     203             : // class SvxSpellCheckDialog ---------------------------------------------
     204             : 
     205           0 : SpellDialog::SpellDialog(
     206             :         SpellDialogChildWindow* pChildWindow,
     207             :         Window * pParent,
     208             :         SfxBindings* _pBindings)
     209             :             : SfxModelessDialog (_pBindings,
     210             :                                     pChildWindow,
     211             :                                     pParent,
     212           0 :                                     CUI_RES(RID_SVXDLG_SPELLCHECK)),
     213             : 
     214           0 :     aLanguageFT     ( this, CUI_RES( FT_LANGUAGE ) ),
     215           0 :     aLanguageLB     ( this, CUI_RES( LB_LANGUAGE ) ),
     216           0 :     aExplainFT      ( this, CUI_RES( FT_EXPLAIN ) ),
     217           0 :     aExplainLink    ( this, CUI_RES( LINK_EXPLAIN ) ),
     218           0 :     aNotInDictFT    ( this, CUI_RES( FT_NOTINDICT ) ),
     219           0 :     aSentenceED      ( this, CUI_RES( ED_NEWWORD ) ),
     220           0 :     aSuggestionFT   ( this, CUI_RES( FT_SUGGESTION ) ),
     221           0 :     aSuggestionLB   ( this, CUI_RES( LB_SUGGESTION ) ),
     222             : 
     223           0 :     aIgnorePB       ( this, CUI_RES( PB_IGNORE ) ),
     224           0 :     aIgnoreAllPB    ( this, CUI_RES( PB_IGNOREALL ) ),
     225           0 :     aIgnoreRulePB   ( this, CUI_RES( PB_IGNORERULE ) ),
     226           0 :     aAddToDictMB    ( this, CUI_RES( MB_ADDTODICT ) ),
     227           0 :     aAddToDictPB    ( this, CUI_RES( PB_ADDTODICT ) ),
     228             : 
     229           0 :     aChangePB       ( this, CUI_RES( PB_CHANGE ) ),
     230           0 :     aChangeAllPB    ( this, CUI_RES( PB_CHANGEALL ) ),
     231           0 :     aAutoCorrPB     ( this, CUI_RES( PB_AUTOCORR ) ),
     232             : 
     233           0 :     aCheckGrammarCB ( this, CUI_RES( CB_CHECK_GRAMMAR ) ),
     234             : 
     235           0 :     aHelpPB         ( this, CUI_RES( PB_HELP ) ),
     236           0 :     aOptionsPB      ( this, CUI_RES( PB_OPTIONS ) ),
     237           0 :     aUndoPB         ( this, CUI_RES( PB_UNDO ) ),
     238           0 :     aClosePB        ( this, CUI_RES( PB_CLOSE ) ),
     239           0 :     aBackgroundGB   ( this, CUI_RES( GB_BACKGROUND ) ),
     240             : 
     241           0 :     aResumeST       ( CUI_RES(ST_RESUME )),
     242             :     aIgnoreOnceST   ( aIgnorePB.GetText()),
     243           0 :     aNoSuggestionsST( CUI_RES(ST_NOSUGGESTIONS)),
     244           0 :     m_sTitleSpelling              ( CUI_RES( ST_SPELLING                        ) ),
     245           0 :     m_sTitleSpellingGrammar       ( CUI_RES( ST_SPELLING_AND_GRAMMAR            ) ),
     246           0 :     m_sTitleSpellingGrammarVendor ( CUI_RES( ST_SPELLING_AND_GRAMMAR_VENDORNAME ) ),
     247             :     aDialogUndoLink( LINK (this, SpellDialog, DialogUndoHdl)),
     248             :     bModified( false ),
     249             :     bFocusLocked( true ),
     250           0 :     rParent         ( *pChildWindow )
     251             : {
     252           0 :     FreeResource();
     253           0 :     xSpell = LinguMgr::GetSpellChecker();
     254           0 :     pImpl = new SpellDialog_Impl;
     255             : 
     256           0 :     const StyleSettings& rSettings = GetSettings().GetStyleSettings();
     257           0 :     Color aCol = rSettings.GetHelpColor();
     258           0 :     Wallpaper aWall( aCol );
     259           0 :     aExplainLink.SetBackground( aWall );
     260           0 :     aExplainFT.SetBackground( aWall );
     261             : 
     262             :     //HelpIds
     263           0 :     aClosePB.       SetHelpId(HID_SPLDLG_BUTTON_CLOSE    );
     264           0 :     aIgnorePB.      SetHelpId(HID_SPLDLG_BUTTON_IGNORE   );
     265           0 :     aIgnoreAllPB.   SetHelpId(HID_SPLDLG_BUTTON_IGNOREALL);
     266           0 :     aIgnoreRulePB.  SetHelpId(HID_SPLDLG_BUTTON_IGNORERULE);
     267           0 :     aChangePB.      SetHelpId(HID_SPLDLG_BUTTON_CHANGE   );
     268           0 :     aChangeAllPB.   SetHelpId(HID_SPLDLG_BUTTON_CHANGEALL);
     269           0 :     aExplainLink.   SetHelpId(HID_SPLDLG_BUTTON_EXPLAIN );
     270           0 :     Init_Impl();
     271             : 
     272             :     // disable controls if service is missing
     273           0 :     if (!xSpell.is())
     274           0 :         Enable( sal_False );
     275             : 
     276             :     Application::PostUserEvent( STATIC_LINK(
     277           0 :                         this, SpellDialog, InitHdl ) );
     278           0 : }
     279             : 
     280             : // -----------------------------------------------------------------------
     281             : 
     282           0 : SpellDialog::~SpellDialog()
     283             : {
     284             :     // save possibly modified user-dictionaries
     285           0 :     Reference< XDictionaryList >  xDicList( SvxGetDictionaryList() );
     286           0 :     if (xDicList.is())
     287             :     {
     288           0 :         linguistic::SaveDictionaries( xDicList );
     289             :     }
     290             : 
     291           0 :     delete aAddToDictMB.GetPopupMenu();
     292           0 :     delete pImpl;
     293           0 : }
     294             : 
     295             : // -----------------------------------------------------------------------
     296             : 
     297           0 : void SpellDialog::Init_Impl()
     298             : {
     299             :     // initialize handler
     300           0 :     aClosePB.SetClickHdl(LINK( this, SpellDialog, CancelHdl ) );
     301           0 :     aChangePB.SetClickHdl(LINK( this, SpellDialog, ChangeHdl ) );
     302           0 :     aChangeAllPB.SetClickHdl(LINK( this, SpellDialog, ChangeAllHdl ) );
     303           0 :     aIgnorePB.SetClickHdl(LINK( this, SpellDialog, IgnoreHdl ) );
     304           0 :     aIgnoreAllPB.SetClickHdl(LINK( this, SpellDialog, IgnoreAllHdl ) );
     305           0 :     aIgnoreRulePB.SetClickHdl(LINK( this, SpellDialog, IgnoreAllHdl ) );
     306           0 :     aUndoPB.SetClickHdl(LINK( this, SpellDialog, UndoHdl ) );
     307             : 
     308           0 :     aAutoCorrPB.SetClickHdl( LINK( this, SpellDialog, ExtClickHdl ) );
     309           0 :     aCheckGrammarCB.SetClickHdl( LINK( this, SpellDialog, CheckGrammarHdl ));
     310           0 :     aOptionsPB .SetClickHdl( LINK( this, SpellDialog, ExtClickHdl ) );
     311             : 
     312           0 :     aSuggestionLB.SetDoubleClickHdl( LINK( this, SpellDialog, ChangeHdl ) );
     313             : 
     314           0 :     aSentenceED.SetModifyHdl(LINK ( this, SpellDialog, ModifyHdl) );
     315             : 
     316           0 :     aAddToDictMB.SetSelectHdl(LINK ( this, SpellDialog, AddToDictSelectHdl ) );
     317           0 :     aAddToDictPB.SetClickHdl(LINK ( this, SpellDialog, AddToDictClickHdl ) );
     318             : 
     319           0 :     aLanguageLB.SetSelectHdl(LINK( this, SpellDialog, LanguageSelectHdl ) );
     320             : 
     321           0 :     aExplainLink.SetClickHdl( LINK( this, SpellDialog, HandleHyperlink ) );
     322             : 
     323             :     // initialize language ListBox
     324           0 :     aLanguageLB.SetLanguageList( LANG_LIST_SPELL_USED, sal_False, sal_False, sal_True );
     325             : 
     326           0 :     aSentenceED.ClearModifyFlag();
     327           0 :     SvxGetChangeAllList()->clear();
     328           0 : }
     329             : 
     330             : // -----------------------------------------------------------------------
     331             : 
     332           0 : void SpellDialog::UpdateBoxes_Impl()
     333             : {
     334             :     sal_Int32 i;
     335           0 :     aSuggestionLB.Clear();
     336             : 
     337           0 :     const SpellErrorDescription* pSpellErrorDescription = aSentenceED.GetAlternatives();
     338             : 
     339           0 :     LanguageType nAltLanguage = LANGUAGE_NONE;
     340           0 :     Sequence< ::rtl::OUString > aNewWords;
     341           0 :     bool bIsGrammarError = false;
     342           0 :     if( pSpellErrorDescription )
     343             :     {
     344           0 :         nAltLanguage    = LanguageTag( pSpellErrorDescription->aLocale ).getLanguageType();
     345           0 :         aNewWords       = pSpellErrorDescription->aSuggestions;
     346           0 :         bIsGrammarError = pSpellErrorDescription->bIsGrammarError;
     347           0 :         aExplainLink.SetURL( pSpellErrorDescription->sExplanationURL );
     348           0 :         aExplainFT.SetText( pSpellErrorDescription->sExplanation );
     349             :     }
     350           0 :     if( pSpellErrorDescription && !pSpellErrorDescription->sDialogTitle.isEmpty() )
     351             :     {
     352             :         // use this function to apply the correct image to be used...
     353           0 :         SetTitle_Impl( nAltLanguage );
     354             :         // then change the title to the one to be actually used
     355           0 :         SetText( pSpellErrorDescription->sDialogTitle );
     356             :     }
     357             :     else
     358           0 :         SetTitle_Impl( nAltLanguage );
     359           0 :     SetSelectedLang_Impl( nAltLanguage );
     360           0 :     int nDicts = InitUserDicts();
     361             : 
     362             :     // enter alternatives
     363           0 :     const ::rtl::OUString *pNewWords = aNewWords.getConstArray();
     364           0 :     const sal_Int32 nSize = aNewWords.getLength();
     365           0 :     for ( i = 0; i < nSize; ++i )
     366             :     {
     367           0 :         String aTmp( pNewWords[i] );
     368           0 :         if ( LISTBOX_ENTRY_NOTFOUND == aSuggestionLB.GetEntryPos( aTmp ) )
     369             :         {
     370           0 :             aSuggestionLB.InsertEntry( aTmp );
     371           0 :             aSuggestionLB.SetEntryFlags(aSuggestionLB.GetEntryCount() - 1, LISTBOX_ENTRY_FLAG_MULTILINE);
     372             :         }
     373           0 :     }
     374           0 :     if(!nSize)
     375           0 :         aSuggestionLB.InsertEntry( aNoSuggestionsST );
     376           0 :     aAutoCorrPB.Enable( nSize > 0 );
     377             : 
     378           0 :     aSuggestionFT.Enable(nSize > 0);
     379           0 :     aSuggestionLB.Enable(nSize > 0);
     380           0 :     if( nSize )
     381             :     {
     382           0 :         aSuggestionLB.SelectEntryPos(0);
     383             :     }
     384           0 :     aChangePB.Enable( nSize > 0);
     385           0 :     aChangeAllPB.Enable(nSize > 0);
     386           0 :     bool bShowChangeAll = !bIsGrammarError;
     387           0 :     aChangeAllPB.Show( bShowChangeAll );
     388           0 :     aExplainFT.Show( !bShowChangeAll );
     389           0 :     aLanguageLB.Enable( bShowChangeAll );
     390           0 :     aIgnoreAllPB.Show( bShowChangeAll );
     391             : 
     392           0 :     aAddToDictMB.Show( bShowChangeAll && nDicts > 1);
     393           0 :     aAddToDictPB.Show( bShowChangeAll && nDicts <= 1);
     394           0 :     aIgnoreRulePB.Show( !bShowChangeAll );
     395           0 :     aIgnoreRulePB.Enable(pSpellErrorDescription && !pSpellErrorDescription->sRuleId.isEmpty());
     396           0 :     aAutoCorrPB.Show( bShowChangeAll && rParent.HasAutoCorrection() );
     397             : 
     398           0 :     bool bHasGrammarChecking = rParent.HasGrammarChecking();
     399           0 :     aCheckGrammarCB.Show( bHasGrammarChecking );
     400           0 :     if( !bHasGrammarChecking )
     401             :     {
     402             :         //resize the dialog to hide the hidden area of the CheckBox
     403           0 :         Size aBackSize = aBackgroundGB.GetSizePixel();
     404           0 :         sal_Int32 nDiff = aBackgroundGB.GetPosPixel().Y() + aBackSize.Height()
     405           0 :                             - aCheckGrammarCB.GetPosPixel().Y();
     406           0 :         aBackSize.Height() -= nDiff;
     407           0 :         aBackgroundGB.SetSizePixel(aBackSize);
     408           0 :         Button* aButtons[] = { &aHelpPB, &aOptionsPB, &aUndoPB, &aClosePB, 0 };
     409           0 :         sal_Int32 nButton = 0;
     410           0 :         while( aButtons[nButton])
     411             :         {
     412           0 :             Point aPos = aButtons[nButton]->GetPosPixel();
     413           0 :             aPos.Y() -= nDiff;
     414           0 :             aButtons[nButton]->SetPosPixel(aPos);
     415           0 :             ++nButton;
     416             :         }
     417           0 :         Size aDlgSize = GetSizePixel();
     418           0 :         aDlgSize.Height() -= nDiff;
     419           0 :         SetSizePixel( aDlgSize );
     420             :     }
     421             :     else
     422             :     {
     423           0 :         bool bHasExplainLink = !aExplainLink.GetURL().isEmpty();
     424           0 :         aExplainLink.Show( bHasExplainLink );
     425             : 
     426           0 :         sal_Int32 nExplainWidth = aExplainLink.GetPosPixel().X() - aExplainFT.GetPosPixel().X();
     427           0 :         if ( !bHasExplainLink )
     428           0 :             nExplainWidth += aExplainLink.GetSizePixel().Width();
     429           0 :         sal_Int32 nExplainHeight = aExplainFT.GetActualHeight();
     430           0 :         sal_Int32 nCurrentHeight = aExplainFT.GetSizePixel().Height();
     431           0 :         if( aExplainFT.GetText().Len() == 0 )
     432             :         {
     433           0 :             nExplainHeight = 0;
     434           0 :             aExplainFT.Hide();
     435           0 :             aExplainLink.Hide();
     436             :         }
     437             : 
     438           0 :         Size aCtlSize = aExplainFT.GetSizePixel();
     439           0 :         aCtlSize.Height() = nExplainHeight;
     440           0 :         aCtlSize.Width() = nExplainWidth;
     441           0 :         aExplainFT.SetSizePixel( aCtlSize );
     442             : 
     443           0 :         aCtlSize = aExplainLink.GetSizePixel();
     444           0 :         aCtlSize.Height() = nExplainHeight;
     445           0 :         aExplainLink.SetSizePixel( aCtlSize );
     446             : 
     447           0 :         sal_Int32 nDiff = - ( nCurrentHeight - nExplainHeight );
     448           0 :         if ( nDiff != 0 )
     449             :         {
     450             :             Control* aControls[] = {
     451             :                 &aNotInDictFT,
     452             :                 &aSentenceED,
     453             :                 &aSuggestionFT,
     454             :                 &aSuggestionLB,
     455             :                 &aIgnorePB,
     456             :                 &aIgnoreAllPB,
     457             :                 &aIgnoreRulePB,
     458             :                 &aAddToDictMB,
     459             :                 &aAddToDictPB,
     460             :                 &aChangePB,
     461             :                 &aChangeAllPB,
     462             :                 &aAutoCorrPB,
     463             :                 &aCheckGrammarCB,
     464             :                 &aHelpPB,
     465             :                 &aOptionsPB,
     466             :                 &aUndoPB,
     467             :                 &aClosePB,
     468             :                 &aBackgroundGB,
     469             :                 0
     470           0 :             };
     471           0 :             sal_Int32 nControl = 0;
     472           0 :             while( aControls[nControl])
     473             :             {
     474           0 :                 Point aPos = aControls[nControl]->GetPosPixel();
     475           0 :                 aPos.Y() += nDiff;
     476           0 :                 aControls[nControl]->SetPosPixel(aPos);
     477           0 :                 ++nControl;
     478             :             }
     479           0 :             Size aDlgSize = GetSizePixel();
     480           0 :             aDlgSize.Height() += nDiff;
     481           0 :             SetSizePixel( aDlgSize );
     482           0 :             Invalidate();
     483             :         }
     484           0 :     }
     485           0 : }
     486             : // -----------------------------------------------------------------------
     487             : 
     488           0 : void SpellDialog::SpellContinue_Impl(bool bUseSavedSentence, bool bIgnoreCurrentError )
     489             : {
     490             :     //initially or after the last error of a sentence MarkNextError will fail
     491             :     //then GetNextSentence() has to be called followed again by MarkNextError()
     492             :     //MarkNextError is not initally called if the UndoEdit mode is active
     493           0 :     bool bNextSentence = false;
     494           0 :     if((!aSentenceED.IsUndoEditMode() && aSentenceED.MarkNextError( bIgnoreCurrentError )) ||
     495           0 :             true == ( bNextSentence = GetNextSentence_Impl(bUseSavedSentence, aSentenceED.IsUndoEditMode()) && aSentenceED.MarkNextError( false )))
     496             :     {
     497           0 :         const SpellErrorDescription* pSpellErrorDescription = aSentenceED.GetAlternatives();
     498           0 :         if( pSpellErrorDescription )
     499             :         {
     500           0 :             UpdateBoxes_Impl();
     501             :             Control* aControls[] =
     502             :             {
     503             :                 &aNotInDictFT,
     504             :                 &aSentenceED,
     505             :                 &aLanguageFT,
     506             :                 0
     507           0 :             };
     508           0 :             sal_Int32 nIdx = 0;
     509           0 :             do
     510             :             {
     511           0 :                 aControls[nIdx]->Enable(sal_True);
     512             :             }
     513           0 :             while(aControls[++nIdx]);
     514             : 
     515             :         }
     516           0 :         if( bNextSentence )
     517             :         {
     518             :             //remove undo if a new sentence is active
     519           0 :             aSentenceED.ResetUndo();
     520           0 :             aUndoPB.Enable(sal_False);
     521             :         }
     522             :     }
     523           0 : }
     524             : /* Initialize, asynchronous to prevent virtial calls
     525             :    from a constructor
     526             :  */
     527           0 : IMPL_STATIC_LINK( SpellDialog, InitHdl, SpellDialog *, EMPTYARG )
     528             : {
     529           0 :     pThis->SetUpdateMode( sal_False );
     530             :     //show or hide AutoCorrect depending on the modules abilities
     531           0 :     pThis->aAutoCorrPB.Show(pThis->rParent.HasAutoCorrection());
     532           0 :     pThis->SpellContinue_Impl();
     533           0 :     pThis->aSentenceED.ResetUndo();
     534           0 :     pThis->aUndoPB.Enable(sal_False);
     535             : 
     536             :     // get current language
     537           0 :     pThis->UpdateBoxes_Impl();
     538             : 
     539             :     // fill dictionary PopupMenu
     540           0 :     pThis->InitUserDicts();
     541             : 
     542           0 :     pThis->LockFocusChanges(true);
     543           0 :     if( pThis->aChangePB.IsEnabled() )
     544           0 :         pThis->aChangePB.GrabFocus();
     545           0 :     else if( pThis->aIgnorePB.IsEnabled() )
     546           0 :         pThis->aIgnorePB.GrabFocus();
     547           0 :     else if( pThis->aClosePB.IsEnabled() )
     548           0 :         pThis->aClosePB.GrabFocus();
     549           0 :     pThis->LockFocusChanges(false);
     550             :     //show grammar CheckBox depending on the modules abilities
     551           0 :     pThis->aCheckGrammarCB.Check( pThis->rParent.IsGrammarChecking() );
     552           0 :     pThis->SetUpdateMode( sal_True );
     553           0 :     pThis->Show();
     554           0 :     return 0;
     555             : };
     556             : 
     557             : // -----------------------------------------------------------------------
     558             : 
     559           0 : IMPL_LINK( SpellDialog, ExtClickHdl, Button *, pBtn )
     560             : {
     561           0 :     if (&aOptionsPB == pBtn)
     562           0 :         StartSpellOptDlg_Impl();
     563           0 :     else if(&aAutoCorrPB == pBtn)
     564             :     {
     565             :         //get the currently selected wrong word
     566           0 :         String sCurrentErrorText = aSentenceED.GetErrorText();
     567             :         //get the wrong word from the XSpellAlternative
     568           0 :         const SpellErrorDescription* pSpellErrorDescription = aSentenceED.GetAlternatives();
     569           0 :         if( pSpellErrorDescription )
     570             :         {
     571           0 :             String sWrong(pSpellErrorDescription->sErrorText);
     572             :             //if the word has not been edited in the MultiLineEdit then
     573             :             //the current suggestion should be used
     574             :             //if it's not the 'no suggestions' entry
     575           0 :             if(sWrong == sCurrentErrorText &&
     576           0 :                     aSuggestionLB.IsEnabled() && aSuggestionLB.GetSelectEntryCount() > 0 &&
     577           0 :                     aNoSuggestionsST != aSuggestionLB.GetSelectEntry())
     578             :             {
     579           0 :                 sCurrentErrorText = aSuggestionLB.GetSelectEntry();
     580             :             }
     581           0 :             if(sWrong != sCurrentErrorText)
     582             :             {
     583           0 :                 SvxPrepareAutoCorrect( sWrong, sCurrentErrorText );
     584           0 :                 LanguageType eLang = GetSelectedLang_Impl();
     585           0 :                 rParent.AddAutoCorrection( sWrong, sCurrentErrorText, eLang );
     586           0 :             }
     587           0 :         }
     588             :     }
     589           0 :     return 0;
     590             : }
     591             : // -----------------------------------------------------------------------
     592           0 : IMPL_LINK( SpellDialog, CheckGrammarHdl, CheckBox*, pBox )
     593             : {
     594           0 :     rParent.SetGrammarChecking( pBox->IsChecked() );
     595           0 :     Impl_Restore();
     596           0 :     return 0;
     597             : }
     598             : 
     599           0 : void SpellDialog::StartSpellOptDlg_Impl()
     600             : {
     601             :     sal_uInt16 aSpellInfos[] =
     602             :     {
     603             :         SID_ATTR_SPELL,SID_ATTR_SPELL,
     604             :         SID_SPELL_MODIFIED, SID_SPELL_MODIFIED,
     605             :         SID_AUTOSPELL_CHECK, SID_AUTOSPELL_CHECK,
     606             :         0
     607           0 :     };
     608           0 :     SfxItemSet aSet( SFX_APP()->GetPool(), aSpellInfos);
     609           0 :     aSet.Put(SfxSpellCheckItem( xSpell, SID_ATTR_SPELL ));
     610             :     SfxSingleTabDialog* pDlg =
     611           0 :         new SfxSingleTabDialog( this, aSet, RID_SFXPAGE_LINGU );
     612           0 :     SfxTabPage* pPage = SvxLinguTabPage::Create( pDlg, aSet );
     613           0 :     ( (SvxLinguTabPage*)pPage )->HideGroups( GROUP_MODULES );
     614           0 :     pDlg->SetTabPage( pPage );
     615           0 :     if(RET_OK == pDlg->Execute())
     616             :     {
     617           0 :         InitUserDicts();
     618           0 :         const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
     619           0 :         if(pOutSet)
     620           0 :             OfaTreeOptionsDialog::ApplyLanguageOptions(*pOutSet);
     621             :     }
     622           0 :     delete pDlg;
     623           0 : }
     624             : 
     625             : namespace
     626             : {
     627           0 :     String getDotReplacementString(const String &rErrorText, const String &rSuggestedReplacement)
     628             :     {
     629           0 :         String aString = rErrorText;
     630             : 
     631             :         //dots are sometimes part of the spelled word but they are not necessarily part of the replacement
     632           0 :         bool bDot = aString.Len() && aString.GetChar(aString.Len() - 1 ) == '.';
     633             : 
     634           0 :         aString = rSuggestedReplacement;
     635             : 
     636           0 :         if(bDot && (!aString.Len() || aString.GetChar(aString.Len() - 1 ) != '.'))
     637           0 :             aString += '.';
     638             : 
     639           0 :         return aString;
     640             :     }
     641             : }
     642             : 
     643             : 
     644           0 : String SpellDialog::getReplacementString() const
     645             : {
     646           0 :     String sOrigString = aSentenceED.GetErrorText();
     647             : 
     648           0 :     String sReplacement(sOrigString);
     649             : 
     650           0 :     if(aSuggestionLB.IsEnabled() &&
     651           0 :             aSuggestionLB.GetSelectEntryCount()>0 &&
     652           0 :             aNoSuggestionsST != aSuggestionLB.GetSelectEntry())
     653           0 :         sReplacement = aSuggestionLB.GetSelectEntry();
     654             : 
     655           0 :     return getDotReplacementString(sOrigString, sReplacement);
     656             : }
     657             : 
     658             : // -----------------------------------------------------------------------
     659             : 
     660           0 : IMPL_LINK_NOARG(SpellDialog, ChangeHdl)
     661             : {
     662           0 :     if(aSentenceED.IsUndoEditMode())
     663             :     {
     664           0 :         SpellContinue_Impl();
     665             :     }
     666             :     else
     667             :     {
     668           0 :         aSentenceED.UndoActionStart( SPELLUNDO_CHANGE_GROUP );
     669           0 :         String aString = getReplacementString();
     670           0 :         aSentenceED.ChangeMarkedWord(aString, GetSelectedLang_Impl());
     671           0 :         SpellContinue_Impl();
     672           0 :         bModified = false;
     673           0 :         aSentenceED.UndoActionEnd();
     674             :     }
     675           0 :     if(!aChangePB.IsEnabled())
     676           0 :         aIgnorePB.GrabFocus();
     677           0 :     return 1;
     678             : }
     679             : 
     680             : // -----------------------------------------------------------------------
     681             : 
     682           0 : IMPL_LINK_NOARG(SpellDialog, ChangeAllHdl)
     683             : {
     684           0 :     aSentenceED.UndoActionStart( SPELLUNDO_CHANGE_GROUP );
     685           0 :     String aString = getReplacementString();
     686           0 :     LanguageType eLang = GetSelectedLang_Impl();
     687             : 
     688             :     // add new word to ChangeAll list
     689           0 :     String  aOldWord( aSentenceED.GetErrorText() );
     690           0 :     SvxPrepareAutoCorrect( aOldWord, aString );
     691           0 :     Reference<XDictionary> aXDictionary( SvxGetChangeAllList(), UNO_QUERY );
     692             :     sal_uInt8 nAdded = linguistic::AddEntryToDic( aXDictionary,
     693             :             aOldWord , sal_True,
     694           0 :             aString, eLang );
     695             : 
     696           0 :     if(nAdded == DIC_ERR_NONE)
     697             :     {
     698             :         SpellUndoAction_Impl* pAction = new SpellUndoAction_Impl(
     699           0 :                         SPELLUNDO_CHANGE_ADD_TO_DICTIONARY, aDialogUndoLink);
     700           0 :         pAction->SetDictionary(aXDictionary);
     701           0 :         pAction->SetAddedWord(aOldWord);
     702           0 :         aSentenceED.AddUndoAction(pAction);
     703             :     }
     704             : 
     705           0 :     aSentenceED.ChangeMarkedWord(aString, eLang);
     706           0 :     SpellContinue_Impl();
     707           0 :     bModified = false;
     708           0 :     aSentenceED.UndoActionEnd();
     709           0 :     return 1;
     710             : }
     711             : // -----------------------------------------------------------------------
     712             : 
     713           0 : IMPL_LINK( SpellDialog, IgnoreAllHdl, Button *, pButton )
     714             : {
     715           0 :     aSentenceED.UndoActionStart( SPELLUNDO_CHANGE_GROUP );
     716             :     // add word to IgnoreAll list
     717           0 :     Reference< XDictionary > aXDictionary( SvxGetIgnoreAllList(), UNO_QUERY );
     718             :     //in case the error has been changed manually it has to be restored
     719           0 :     aSentenceED.RestoreCurrentError();
     720           0 :     if( pButton == &aIgnoreRulePB )
     721             :     {
     722           0 :         const SpellErrorDescription* pSpellErrorDescription = aSentenceED.GetAlternatives();
     723             :         try
     724             :         {
     725           0 :             if( pSpellErrorDescription && pSpellErrorDescription->xGrammarChecker.is() )
     726             :             {
     727           0 :                 pSpellErrorDescription->xGrammarChecker->ignoreRule( pSpellErrorDescription->sRuleId,
     728           0 :                     pSpellErrorDescription->aLocale );
     729             :             }
     730             :         }
     731           0 :         catch( const uno::Exception& )
     732             :         {
     733             :         }
     734             :     }
     735             :     else
     736             :     {
     737           0 :         String sErrorText(aSentenceED.GetErrorText());
     738             :         sal_uInt8 nAdded = linguistic::AddEntryToDic( aXDictionary,
     739             :             sErrorText, sal_False,
     740           0 :             ::rtl::OUString(), LANGUAGE_NONE );
     741           0 :         if(nAdded == DIC_ERR_NONE)
     742             :         {
     743             :             SpellUndoAction_Impl* pAction = new SpellUndoAction_Impl(
     744           0 :                             SPELLUNDO_CHANGE_ADD_TO_DICTIONARY, aDialogUndoLink);
     745           0 :             pAction->SetDictionary(aXDictionary);
     746           0 :             pAction->SetAddedWord(sErrorText);
     747           0 :             aSentenceED.AddUndoAction(pAction);
     748           0 :         }
     749             :     }
     750             : 
     751           0 :     SpellContinue_Impl();
     752           0 :     bModified = false;
     753           0 :     aSentenceED.UndoActionEnd();
     754           0 :     return 1;
     755             : }
     756             : 
     757             : //-----------------------------------------------------------------------
     758           0 : IMPL_LINK_NOARG(SpellDialog, UndoHdl)
     759             : {
     760           0 :     aSentenceED.Undo();
     761           0 :     if(!aSentenceED.GetUndoActionCount())
     762           0 :         aUndoPB.Enable(sal_False);
     763           0 :     return 0;
     764             : }
     765             : 
     766             : //-----------------------------------------------------------------------
     767           0 : IMPL_LINK( SpellDialog, DialogUndoHdl, SpellUndoAction_Impl*, pAction )
     768             : {
     769           0 :     switch(pAction->GetId())
     770             :     {
     771             :         case SPELLUNDO_CHANGE_TEXTENGINE:
     772             :         {
     773           0 :             if(pAction->IsEnableChangePB())
     774           0 :                 aChangePB.Enable(sal_False);
     775           0 :             if(pAction->IsEnableChangeAllPB())
     776           0 :                 aChangeAllPB.Enable(sal_False);
     777             :         }
     778           0 :         break;
     779             :         case SPELLUNDO_CHANGE_NEXTERROR:
     780             :         {
     781           0 :             aSentenceED.MoveErrorMarkTo((sal_uInt16)pAction->GetOldErrorStart(), (sal_uInt16)pAction->GetOldErrorEnd(), false);
     782           0 :             if(pAction->IsErrorLanguageSelected())
     783             :             {
     784           0 :                 UpdateBoxes_Impl();
     785             :             }
     786             :         }
     787           0 :         break;
     788             :         case SPELLUNDO_CHANGE_ADD_TO_DICTIONARY:
     789             :         {
     790           0 :             if(pAction->GetDictionary().is())
     791           0 :                 pAction->GetDictionary()->remove(pAction->GetAddedWord());
     792             :         }
     793           0 :         break;
     794             :         case SPELLUNDO_MOVE_ERROREND :
     795             :         {
     796           0 :             if(pAction->GetOffset() != 0)
     797           0 :                 aSentenceED.MoveErrorEnd(pAction->GetOffset());
     798             :         }
     799           0 :         break;
     800             :         case SPELLUNDO_UNDO_EDIT_MODE :
     801             :         {
     802             :             //refill the dialog with the currently spelled sentence - throw away all changes
     803           0 :             SpellContinue_Impl(true);
     804             :         }
     805           0 :         break;
     806             :         case SPELLUNDO_ADD_IGNORE_RULE:
     807             :             //undo of ignored rules is not supported
     808           0 :         break;
     809             :     }
     810             : 
     811           0 :     return 0;
     812             : }
     813             : // -----------------------------------------------------------------------
     814           0 : void SpellDialog::Impl_Restore()
     815             : {
     816             :     //clear the "ChangeAllList"
     817           0 :     SvxGetChangeAllList()->clear();
     818             :     //get a new sentence
     819           0 :     aSentenceED.SetText(rtl::OUString());
     820           0 :     aSentenceED.ResetModified();
     821             :     //Resolves: fdo#39348 refill the dialog with the currently spelled sentence
     822           0 :     SpellContinue_Impl(true);
     823           0 :     aIgnorePB.SetText(aIgnoreOnceST);
     824           0 : }
     825             : 
     826           0 : IMPL_LINK_NOARG(SpellDialog, IgnoreHdl)
     827             : {
     828           0 :     if(aIgnorePB.GetText() == aResumeST)
     829             :     {
     830           0 :         Impl_Restore();
     831             :     }
     832             :     else
     833             :     {
     834             :         //in case the error has been changed manually it has to be restored,
     835             :         // since the users choice now was to ignore the error
     836           0 :         aSentenceED.RestoreCurrentError();
     837             : 
     838             :         // the word is being ignored
     839           0 :         SpellContinue_Impl( false, true );
     840             :     }
     841           0 :     return 1;
     842             : }
     843             : 
     844             : // -----------------------------------------------------------------------
     845             : 
     846           0 : sal_Bool SpellDialog::Close()
     847             : {
     848           0 :     GetBindings().GetDispatcher()->
     849           0 :         Execute(rParent.GetType(),
     850           0 :         SFX_CALLMODE_ASYNCHRON|SFX_CALLMODE_RECORD);
     851           0 :     return sal_True;
     852             : }
     853             : // -----------------------------------------------------------------------
     854             : 
     855           0 : void SpellDialog::SetSelectedLang_Impl( LanguageType nLang )
     856             : {
     857           0 :     aLanguageLB.SelectLanguage( nLang );
     858           0 : }
     859             : 
     860             : // -----------------------------------------------------------------------
     861             : 
     862           0 : LanguageType SpellDialog::GetSelectedLang_Impl() const
     863             : {
     864           0 :     sal_Int16 nLang = aLanguageLB.GetSelectLanguage();
     865           0 :     return nLang;
     866             : }
     867             : 
     868             : //-------------------------------------------------
     869           0 : IMPL_LINK(SpellDialog, LanguageSelectHdl, SvxLanguageBox*, pBox)
     870             : {
     871             :     //If selected language changes, then add->list should be regenerated to
     872             :     //match
     873           0 :     InitUserDicts();
     874             : 
     875             :     //if currently an error is selected then search for alternatives for
     876             :     //this word and fill the alternatives ListBox accordingly
     877           0 :     String sError = aSentenceED.GetErrorText();
     878           0 :     aSuggestionLB.Clear();
     879           0 :     if(sError.Len())
     880             :     {
     881           0 :         LanguageType eLanguage = pBox->GetSelectLanguage();
     882           0 :         Reference <XSpellAlternatives> xAlt = xSpell->spell( sError, eLanguage,
     883           0 :                                             Sequence< PropertyValue >() );
     884           0 :         if( xAlt.is() )
     885           0 :             aSentenceED.SetAlternatives( xAlt );
     886             :         else
     887             :         {
     888           0 :             aSentenceED.ChangeMarkedWord( sError, eLanguage );
     889           0 :             SpellContinue_Impl();
     890             :         }
     891             : 
     892           0 :          aSentenceED.AddUndoAction(new SpellUndoAction_Impl(SPELLUNDO_CHANGE_LANGUAGE, aDialogUndoLink));
     893             :     }
     894           0 :     SpellDialog::UpdateBoxes_Impl();
     895           0 :     return 0;
     896             : }
     897             : // -----------------------------------------------------------------------
     898             : 
     899           0 : void SpellDialog::SetLanguage( sal_uInt16 nLang )
     900             : /*
     901             :     Description:
     902             :     If the language has been changed in thesaurus,
     903             :     it must be changed here, too.
     904             : */
     905             : {
     906           0 :     SetTitle_Impl( nLang );
     907           0 :     aLanguageLB.SelectLanguage( nLang );
     908           0 : }
     909             : 
     910           0 : static Image lcl_GetImageFromPngUrl( const ::rtl::OUString &rFileUrl )
     911             : {
     912           0 :     Image aRes;
     913           0 :     ::rtl::OUString aTmp;
     914           0 :     osl::FileBase::getSystemPathFromFileURL( rFileUrl, aTmp );
     915           0 :     Graphic aGraphic;
     916           0 :     const String aFilterName( RTL_CONSTASCII_USTRINGPARAM( IMP_PNG ) );
     917           0 :     if( GRFILTER_OK == GraphicFilter::LoadGraphic( aTmp, aFilterName, aGraphic ) )
     918             :     {
     919           0 :         aRes = Image( aGraphic.GetBitmapEx() );
     920             :     }
     921           0 :     return aRes;
     922             : }
     923           0 : void SpellDialog::SetTitle_Impl(LanguageType nLang)
     924             : {
     925           0 :     String sTitle( m_sTitleSpelling );
     926           0 :     if( rParent.HasGrammarChecking() )
     927             :     {
     928           0 :         String sVendor;
     929           0 :         const SpellErrorDescription* pSpellErrorDescription = aSentenceED.GetAlternatives();
     930           0 :         if( pSpellErrorDescription && !pSpellErrorDescription->sServiceName.isEmpty() )
     931             :         {
     932           0 :             uno::Reference< lang::XServiceDisplayName > xDisplayName( pSpellErrorDescription->xGrammarChecker, uno::UNO_QUERY );
     933           0 :             if( xDisplayName.is() )
     934           0 :                 sVendor = xDisplayName->getServiceDisplayName( pSpellErrorDescription->aLocale );
     935             :         }
     936             : 
     937           0 :         if( sVendor.Len() )
     938             :         {
     939           0 :             sTitle = m_sTitleSpellingGrammarVendor;
     940           0 :             sTitle.SearchAndReplaceAscii( "$VendorName", sVendor );
     941             :         }
     942             :         else
     943             :         {
     944           0 :             sTitle = m_sTitleSpellingGrammar;
     945           0 :         }
     946             :     }
     947           0 :     sTitle.SearchAndReplaceAscii( "$LANGUAGE ($LOCATION)", SvtLanguageTable::GetLanguageString(nLang) );
     948           0 :     SetText( sTitle );
     949           0 : }
     950             : 
     951           0 : int SpellDialog::InitUserDicts()
     952             : {
     953           0 :     const LanguageType nLang = aLanguageLB.GetSelectLanguage();
     954             : 
     955           0 :     const Reference< XDictionary >  *pDic = 0;
     956             : 
     957             :     // get list of dictionaries
     958           0 :     Reference< XDictionaryList >  xDicList( SvxGetDictionaryList() );
     959           0 :     if (xDicList.is())
     960             :     {
     961             :         // add active, positive dictionary to dic-list (if not already done).
     962             :         // This is to ensure that there is at least on dictionary to which
     963             :         // words could be added.
     964           0 :         Reference< XDictionary >  xDic( SvxGetOrCreatePosDic( xDicList ) );
     965           0 :         if (xDic.is())
     966           0 :             xDic->setActive( sal_True );
     967             : 
     968           0 :         pImpl->aDics = xDicList->getDictionaries();
     969             :     }
     970             : 
     971           0 :     SvtLinguConfig aCfg;
     972             : 
     973             :     // list suitable dictionaries
     974           0 :     bool bEnable = false;
     975           0 :     const sal_Int32 nSize = pImpl->aDics.getLength();
     976           0 :     pDic = pImpl->aDics.getConstArray();
     977           0 :     delete aAddToDictMB.GetPopupMenu();
     978           0 :     PopupMenu* pMenu = new PopupMenu;
     979           0 :     pMenu->SetMenuFlags(MENU_FLAG_NOAUTOMNEMONICS);
     980           0 :     sal_uInt16 nItemId = 1;     // menu items should be enumerated from 1 and not 0
     981           0 :     for (sal_Int32 i = 0; i < nSize; ++i)
     982             :     {
     983           0 :         uno::Reference< linguistic2::XDictionary >  xDicTmp( pDic[i], uno::UNO_QUERY );
     984           0 :         if (!xDicTmp.is() || SvxGetIgnoreAllList() == xDicTmp)
     985           0 :             continue;
     986             : 
     987           0 :         uno::Reference< frame::XStorable > xStor( xDicTmp, uno::UNO_QUERY );
     988           0 :         LanguageType nActLanguage = LanguageTag( xDicTmp->getLocale() ).getLanguageType();
     989           0 :         if( xDicTmp->isActive()
     990           0 :             &&  xDicTmp->getDictionaryType() != linguistic2::DictionaryType_NEGATIVE
     991             :             && (nLang == nActLanguage || LANGUAGE_NONE == nActLanguage )
     992           0 :             && (!xStor.is() || !xStor->isReadonly()) )
     993             :         {
     994           0 :             pMenu->InsertItem( nItemId, xDicTmp->getName() );
     995           0 :             bEnable = sal_True;
     996             : 
     997           0 :             uno::Reference< lang::XServiceInfo > xSvcInfo( xDicTmp, uno::UNO_QUERY );
     998           0 :             if (xSvcInfo.is())
     999             :             {
    1000             :                 OUString aDictionaryImageUrl( aCfg.GetSpellAndGrammarContextDictionaryImage(
    1001           0 :                         xSvcInfo->getImplementationName()) );
    1002           0 :                 if (!aDictionaryImageUrl.isEmpty())
    1003             :                 {
    1004           0 :                     Image aImage( lcl_GetImageFromPngUrl( aDictionaryImageUrl ) );
    1005           0 :                     pMenu->SetItemImage( nItemId, aImage );
    1006           0 :                 }
    1007             :             }
    1008             : 
    1009           0 :             ++nItemId;
    1010             :         }
    1011           0 :     }
    1012           0 :     aAddToDictMB.SetPopupMenu(pMenu);
    1013           0 :     aAddToDictMB.Enable( bEnable );
    1014           0 :     aAddToDictPB.Enable( bEnable );
    1015             : 
    1016           0 :     int nDicts = nItemId-1;
    1017             : 
    1018           0 :     aAddToDictMB.Show( nDicts > 1 );
    1019           0 :     aAddToDictPB.Show( nDicts <= 1 );
    1020             : 
    1021           0 :     return nDicts;
    1022             : }
    1023             : 
    1024             : //-----------------------------------------------------------------------
    1025           0 : IMPL_LINK(SpellDialog, AddToDictClickHdl, PushButton*, EMPTYARG )
    1026             : {
    1027           0 :     return AddToDictionaryExecute(1, aAddToDictMB.GetPopupMenu());
    1028             : }
    1029             : 
    1030             : //-----------------------------------------------------------------------
    1031           0 : IMPL_LINK(SpellDialog, AddToDictSelectHdl, MenuButton*, pButton )
    1032             : {
    1033           0 :     return AddToDictionaryExecute(pButton->GetCurItemId(), pButton->GetPopupMenu());
    1034             : }
    1035             : 
    1036             : //-----------------------------------------------------------------------
    1037           0 : int SpellDialog::AddToDictionaryExecute( sal_uInt16 nItemId, PopupMenu *pMenu )
    1038             : {
    1039           0 :     aSentenceED.UndoActionStart( SPELLUNDO_CHANGE_GROUP );
    1040             : 
    1041             :     //GetErrorText() returns the current error even if the text is already
    1042             :     //manually changed
    1043           0 :     const String aNewWord= aSentenceED.GetErrorText();
    1044             : 
    1045           0 :     String aDicName ( pMenu->GetItemText( nItemId ) );
    1046             : 
    1047           0 :     uno::Reference< linguistic2::XDictionary >      xDic;
    1048           0 :     uno::Reference< linguistic2::XDictionaryList >  xDicList( SvxGetDictionaryList() );
    1049           0 :     if (xDicList.is())
    1050           0 :         xDic = xDicList->getDictionaryByName( aDicName );
    1051             : 
    1052           0 :     sal_Int16 nAddRes = DIC_ERR_UNKNOWN;
    1053           0 :     if (xDic.is())
    1054             :     {
    1055           0 :         nAddRes = linguistic::AddEntryToDic( xDic, aNewWord, sal_False, OUString(), LANGUAGE_NONE );
    1056             :         // save modified user-dictionary if it is persistent
    1057           0 :         uno::Reference< frame::XStorable >  xSavDic( xDic, uno::UNO_QUERY );
    1058           0 :         if (xSavDic.is())
    1059           0 :             xSavDic->store();
    1060             : 
    1061           0 :         if (nAddRes == DIC_ERR_NONE)
    1062             :         {
    1063             :             SpellUndoAction_Impl* pAction = new SpellUndoAction_Impl(
    1064           0 :                             SPELLUNDO_CHANGE_ADD_TO_DICTIONARY, aDialogUndoLink);
    1065           0 :             pAction->SetDictionary( xDic );
    1066           0 :             pAction->SetAddedWord( aNewWord );
    1067           0 :             aSentenceED.AddUndoAction( pAction );
    1068             :         }
    1069             :         // failed because there is already an entry?
    1070           0 :         if (DIC_ERR_NONE != nAddRes && xDic->getEntry( aNewWord ).is())
    1071           0 :             nAddRes = DIC_ERR_NONE;
    1072             :     }
    1073           0 :     if (DIC_ERR_NONE != nAddRes)
    1074             :     {
    1075           0 :         SvxDicError( this, nAddRes );
    1076           0 :         return 0; // don't continue
    1077             :     }
    1078             : 
    1079             :     // go on
    1080           0 :     SpellContinue_Impl();
    1081           0 :     aSentenceED.UndoActionEnd();
    1082           0 :     return 0;
    1083             : }
    1084             : 
    1085             : //-----------------------------------------------------------------------
    1086           0 : IMPL_LINK(SpellDialog, ModifyHdl, SentenceEditWindow_Impl*, pEd)
    1087             : {
    1088           0 :     if (&aSentenceED == pEd)
    1089             :     {
    1090           0 :         bModified = true;
    1091           0 :         aSuggestionLB.SetNoSelection();
    1092           0 :         aSuggestionLB.Disable();
    1093           0 :         String sNewText( aSentenceED.GetText() );
    1094           0 :         aAutoCorrPB.Enable( sNewText != aSentenceED.GetText() );
    1095           0 :         SpellUndoAction_Impl* pSpellAction = new SpellUndoAction_Impl(SPELLUNDO_CHANGE_TEXTENGINE, aDialogUndoLink);
    1096           0 :         if(!aChangeAllPB.IsEnabled())
    1097             :         {
    1098           0 :             aChangeAllPB.Enable();
    1099           0 :             pSpellAction->SetEnableChangeAllPB();
    1100             :         }
    1101           0 :         if(!aChangePB.IsEnabled())
    1102             :         {
    1103           0 :             aChangePB.Enable();
    1104           0 :             pSpellAction->SetEnableChangePB();
    1105             :         }
    1106           0 :         aSentenceED.AddUndoAction(pSpellAction);
    1107             :     }
    1108           0 :     return 0;
    1109             : };
    1110             : 
    1111             : //-----------------------------------------------------------------------
    1112           0 : IMPL_LINK_NOARG(SpellDialog, CancelHdl)
    1113             : {
    1114             :     //apply changes and ignored text parts first - if there are any
    1115           0 :     rParent.ApplyChangedSentence(aSentenceED.CreateSpellPortions(true), false);
    1116           0 :     Close();
    1117           0 :     return 0;
    1118             : }
    1119             : 
    1120             : //-----------------------------------------------------------------------
    1121           0 : void SpellDialog::Paint( const Rectangle& rRect )
    1122             : {
    1123           0 :     ModelessDialog::Paint(rRect );
    1124           0 :     Rectangle aRect(aBackgroundGB.GetPosPixel(), aBackgroundGB.GetSizePixel());
    1125           0 :     DecorationView aDecoView( this );
    1126           0 :     aDecoView.DrawButton( aRect, BUTTON_DRAW_NOFILL);
    1127           0 : }
    1128             : 
    1129             : //-----------------------------------------------------------------------
    1130           0 : long SpellDialog::Notify( NotifyEvent& rNEvt )
    1131             : {
    1132             :     /* #i38338#
    1133             :     *   FIXME: LoseFocus and GetFocus are signals from vcl that
    1134             :     *   a window actually got/lost the focus, it never should be
    1135             :     *   forwarded from another window, that is simply wrong.
    1136             :     *   FIXME: overloading the virtual methods GetFocus and LoseFocus
    1137             :     *   in SpellDialogChildWindow by making them pure is at least questionable.
    1138             :     *   The only sensible thing would be to call the new Method differently,
    1139             :     *   e.g. DialogGot/LostFocus or so.
    1140             :     */
    1141           0 :     if( IsVisible() && !bFocusLocked )
    1142             :     {
    1143           0 :         if( rNEvt.GetType() ==  EVENT_GETFOCUS )
    1144             :         {
    1145             :             //notify the child window of the focus change
    1146           0 :             rParent.GetFocus();
    1147             :         }
    1148           0 :         else if( rNEvt.GetType() == EVENT_LOSEFOCUS )
    1149             :         {
    1150             :             //notify the child window of the focus change
    1151           0 :             rParent.LoseFocus();
    1152             :         }
    1153             :     }
    1154           0 :     return SfxModelessDialog::Notify(rNEvt);
    1155             : }
    1156             : 
    1157             : //-------------------------------------------------
    1158           0 : void SpellDialog::InvalidateDialog()
    1159             : {
    1160           0 :     if( bFocusLocked )
    1161           0 :         return;
    1162           0 :     aIgnorePB.SetText(aResumeST);
    1163             :     Window* aDisableArr[] =
    1164             :             {
    1165             :                 &aNotInDictFT,
    1166             :                 &aSentenceED,
    1167             :                 &aSuggestionFT,
    1168             :                 &aSuggestionLB,
    1169             :                 &aLanguageFT,
    1170             :                 &aLanguageLB,
    1171             :                 &aIgnoreAllPB,
    1172             :                 &aIgnoreRulePB,
    1173             :                 &aAddToDictMB,
    1174             :                 &aAddToDictPB,
    1175             :                 &aChangePB,
    1176             :                 &aChangeAllPB,
    1177             :                 &aAutoCorrPB,
    1178             :                 &aUndoPB,
    1179             :                 0
    1180           0 :             };
    1181           0 :     sal_Int16 i = 0;
    1182           0 :     while(aDisableArr[i])
    1183             :     {
    1184           0 :         aDisableArr[i]->Enable(sal_False);
    1185           0 :         i++;
    1186             :     }
    1187           0 :     SfxModelessDialog::Deactivate();
    1188             : }
    1189             : 
    1190             : //-----------------------------------------------------------------------
    1191           0 : bool SpellDialog::GetNextSentence_Impl(bool bUseSavedSentence, bool bRecheck)
    1192             : {
    1193           0 :     bool bRet = false;
    1194           0 :     if(!bUseSavedSentence)
    1195             :     {
    1196             :         //apply changes and ignored text parts
    1197           0 :         rParent.ApplyChangedSentence(aSentenceED.CreateSpellPortions(true), bRecheck);
    1198             :     }
    1199           0 :     aSentenceED.ResetIgnoreErrorsAt();
    1200           0 :     aSentenceED.ResetModified();
    1201           0 :     SpellPortions aSentence = bUseSavedSentence ? m_aSavedSentence : rParent.GetNextWrongSentence( bRecheck );
    1202           0 :     if(!bUseSavedSentence)
    1203           0 :         m_aSavedSentence = aSentence;
    1204           0 :     bool bHasReplaced = false;
    1205           0 :     while(!aSentence.empty())
    1206             :     {
    1207             :         //apply all changes that are already part of the "ChangeAllList"
    1208             :         //returns true if the list still contains errors after the changes have been applied
    1209             : 
    1210           0 :         if(!ApplyChangeAllList_Impl(aSentence, bHasReplaced))
    1211             :         {
    1212           0 :             rParent.ApplyChangedSentence(aSentence, bRecheck);
    1213           0 :             aSentence = rParent.GetNextWrongSentence( bRecheck );
    1214             :         }
    1215             :         else
    1216           0 :             break;
    1217             :     }
    1218             : 
    1219           0 :     if(!aSentence.empty())
    1220             :     {
    1221           0 :         SpellPortions::iterator aStart = aSentence.begin();
    1222           0 :         rtl::OUString sText;
    1223           0 :         while(aStart != aSentence.end())
    1224             :         {
    1225             :             // hidden text has to be ignored
    1226           0 :             if(!aStart->bIsHidden)
    1227           0 :                 sText += aStart->sText;
    1228           0 :             ++aStart;
    1229             :         }
    1230           0 :         aSentenceED.SetText(sText);
    1231           0 :         aStart = aSentence.begin();
    1232           0 :         sal_Int32 nStartPosition = 0;
    1233           0 :         sal_Int32 nEndPosition = 0;
    1234             : 
    1235           0 :         while(aStart != aSentence.end())
    1236             :         {
    1237             :             // hidden text has to be ignored
    1238           0 :             if(!aStart->bIsHidden)
    1239             :             {
    1240           0 :                 nEndPosition += aStart->sText.getLength();
    1241           0 :                 if(aStart->xAlternatives.is())
    1242             :                 {
    1243           0 :                     uno::Reference< container::XNamed > xNamed( aStart->xAlternatives, uno::UNO_QUERY );
    1244           0 :                     ::rtl::OUString sServiceName;
    1245           0 :                     if( xNamed.is() )
    1246           0 :                         sServiceName = xNamed->getName();
    1247           0 :                     SpellErrorDescription aDesc( false, aStart->xAlternatives->getWord(),
    1248           0 :                                     aStart->xAlternatives->getLocale(), aStart->xAlternatives->getAlternatives(), 0, sServiceName);
    1249           0 :                     aSentenceED.SetAttrib( SpellErrorAttrib(aDesc), 0, (sal_uInt16) nStartPosition, (sal_uInt16) nEndPosition );
    1250             :                 }
    1251           0 :                 else if(aStart->bIsGrammarError )
    1252             :                 {
    1253           0 :                     beans::PropertyValues  aProperties = aStart->aGrammarError.aProperties;
    1254           0 :                     rtl::OUString sFullCommentURL;
    1255           0 :                     sal_Int32 i = 0;
    1256           0 :                     while ( sFullCommentURL.isEmpty() && i < aProperties.getLength() )
    1257             :                     {
    1258           0 :                         if ( aProperties[i].Name == "FullCommentURL" )
    1259             :                         {
    1260           0 :                             uno::Any aValue = aProperties[i].Value;
    1261           0 :                             aValue >>= sFullCommentURL;
    1262             :                         }
    1263           0 :                         ++i;
    1264             :                     }
    1265             : 
    1266           0 :                     uno::Reference< lang::XServiceInfo > xInfo( aStart->xGrammarChecker, uno::UNO_QUERY );
    1267             :                     SpellErrorDescription aDesc( true,
    1268           0 :                         aStart->sText,
    1269           0 :                         LanguageTag( aStart->eLanguage ).getLocale(),
    1270           0 :                         aStart->aGrammarError.aSuggestions,
    1271           0 :                         aStart->xGrammarChecker,
    1272           0 :                         xInfo->getImplementationName(),
    1273           0 :                         &aStart->sDialogTitle,
    1274           0 :                         &aStart->aGrammarError.aFullComment,
    1275           0 :                         &aStart->aGrammarError.aRuleIdentifier,
    1276           0 :                         &sFullCommentURL );
    1277           0 :                     aSentenceED.SetAttrib( SpellErrorAttrib(aDesc), 0, (sal_uInt16) nStartPosition, (sal_uInt16) nEndPosition );
    1278             :                 }
    1279           0 :                 if(aStart->bIsField)
    1280           0 :                     aSentenceED.SetAttrib( SpellBackgroundAttrib(COL_LIGHTGRAY), 0, (sal_uInt16) nStartPosition, (sal_uInt16) nEndPosition );
    1281           0 :                 aSentenceED.SetAttrib( SpellLanguageAttrib(aStart->eLanguage), 0, (sal_uInt16) nStartPosition, (sal_uInt16) nEndPosition );
    1282           0 :                 nStartPosition = nEndPosition;
    1283             :             }
    1284           0 :             ++aStart;
    1285             :         }
    1286             :         //the edit field needs to be modified to apply the change from the ApplyChangeAllList
    1287           0 :         if(!bHasReplaced)
    1288           0 :             aSentenceED.ClearModifyFlag();
    1289           0 :         aSentenceED.ResetUndo();
    1290           0 :         aUndoPB.Enable(sal_False);
    1291           0 :         bRet = nStartPosition > 0;
    1292             :     }
    1293           0 :     return bRet;
    1294             : }
    1295             : /*-------------------------------------------------------------------------
    1296             :     replace errrors that have a replacement in the ChangeAllList
    1297             :     returns false if the result doesn't contain errors after the replacement
    1298             :   -----------------------------------------------------------------------*/
    1299           0 : bool SpellDialog::ApplyChangeAllList_Impl(SpellPortions& rSentence, bool &bHasReplaced)
    1300             : {
    1301           0 :     bHasReplaced = false;
    1302           0 :     bool bRet = true;
    1303           0 :     SpellPortions::iterator aStart = rSentence.begin();
    1304           0 :     Reference<XDictionary> xChangeAll( SvxGetChangeAllList(), UNO_QUERY );
    1305           0 :     if(!xChangeAll->getCount())
    1306           0 :         return bRet;
    1307           0 :     bRet = false;
    1308           0 :     while(aStart != rSentence.end())
    1309             :     {
    1310           0 :         if(aStart->xAlternatives.is())
    1311             :         {
    1312           0 :             const rtl::OUString &rString = aStart->sText;
    1313             : 
    1314           0 :             Reference<XDictionaryEntry> xEntry = xChangeAll->getEntry(rString);
    1315             : 
    1316           0 :             if(xEntry.is())
    1317             :             {
    1318           0 :                 aStart->sText = getDotReplacementString(rString, xEntry->getReplacementText());
    1319           0 :                 aStart->xAlternatives = 0;
    1320           0 :                 bHasReplaced = true;
    1321             :             }
    1322             :             else
    1323           0 :                 bRet = true;
    1324             :         }
    1325           0 :         else if( aStart->bIsGrammarError )
    1326           0 :             bRet = true;
    1327           0 :         ++aStart;
    1328             :     }
    1329           0 :     return bRet;
    1330             : }
    1331             : 
    1332             : //-----------------------------------------------------------------------
    1333           0 : SentenceEditWindow_Impl::SentenceEditWindow_Impl( SpellDialog* pParent, const ResId& rResId ) :
    1334             :     MultiLineEdit( pParent, rResId ),
    1335             :     m_nErrorStart(0),
    1336             :     m_nErrorEnd(0),
    1337           0 :     m_bIsUndoEditMode(false)
    1338             : {
    1339           0 :     DisableSelectionOnFocus();
    1340           0 : }
    1341             : 
    1342             : //-----------------------------------------------------------------------
    1343           0 : SentenceEditWindow_Impl::~SentenceEditWindow_Impl()
    1344             : {
    1345           0 : }
    1346             : /*-------------------------------------------------------------------------
    1347             :     The selection before inputting a key may have a range or not
    1348             :     and it may be inside or outside of field or error attributes.
    1349             :     A range may include the attribute partially, completely or together
    1350             :     with surrounding text. It may also contain more than one attribute
    1351             :     or no attribute at all.
    1352             :     Depending on this starting conditions some actions are necessary:
    1353             :     Attempts to delete a field are only allowed if the selection is the same
    1354             :     as the field's selection. Otherwise the field has to be selected and the key
    1355             :     input action has to be skipped.
    1356             :     Input of text at the start of the field requires the field attribute to be
    1357             :     corrected - it is not allowed to grow.
    1358             : 
    1359             :     In case of errors the appending of text should grow the error attribute because
    1360             :     that is what the user usually wants to do.
    1361             : 
    1362             :     Backspace at the start of the attribute requires to find out if a field ends
    1363             :     directly in front of the cursor position. In case of a field this attribute has to be
    1364             :     selected otherwise the key input method is allowed.
    1365             : 
    1366             :     All changes outside of the error attributes switch the dialog mode to a "Undo edit" state that
    1367             :     removes all visible attributes and switches off further attribute checks.
    1368             :     Undo in this restarts the dialog with a current sentence newly presented.
    1369             :     All changes to the sentence are undone including the ones before the "Undo edit state" has been reached
    1370             : 
    1371             :     We end up with 9 types of selection
    1372             :     1 (LEFT_NO)     - no range, start of attribute - can also be 3 at the same time
    1373             :     2 (INSIDE_NO)   - no range, inside of attribute
    1374             :     3 (RIGHT_NO)    - no range, end of attribute - can also be 1 at the same time
    1375             :     4 (FULL)        - range, same as attribute
    1376             :     5 (INSIDE_YES)  - range, inside of the attribute
    1377             :     6 (BRACE)- range, from outside of the attribute to the inside or
    1378             :                 including the complete attribute and something outside,
    1379             :                 maybe more than one attribute
    1380             :     7 (OUTSIDE_NO)  - no range, not at an attribute
    1381             :     8 (OUTSIDE_YES) - range, completely outside of all attributes
    1382             : 
    1383             :     What has to be done depending on the attribute type involved
    1384             :     possible actions:   UE - Undo edit mode
    1385             :                         CO - Continue, no additional action is required
    1386             :                         FS - Field has to be completely selected
    1387             :                         EX - The attribute has to be expanded to include the added text
    1388             : 
    1389             :     1 - backspace                   delete                      any other
    1390             :         UE                          on field FS on error CO     on field FS on error CO
    1391             : 
    1392             :     2 - on field FS on error C
    1393             :     3 - backspace                   delete                      any other
    1394             :         on field FS on error CO     UE                          on field UE on error EX
    1395             : 
    1396             :     if 1 and 3 happen to apply both then backspace and other handling is 1 delete is 3
    1397             : 
    1398             :     4 - on field UE and on error CO
    1399             :     5 - on field FS and on error CO
    1400             :     6 - on field FS and on error UE
    1401             :     7 - UE
    1402             :     8 - UE
    1403             :   -----------------------------------------------------------------------*/
    1404             : #define     INVALID     0
    1405             : #define     LEFT_NO     1
    1406             : #define     INSIDE_NO   2
    1407             : #define     RIGHT_NO    3
    1408             : #define     FULL        4
    1409             : #define     INSIDE_YES  5
    1410             : #define     BRACE       6
    1411             : #define     OUTSIDE_NO  7
    1412             : #define     OUTSIDE_YES 8
    1413             : 
    1414             : #define ACTION_UNDOEDIT    0
    1415             : #define ACTION_CONTINUE    1
    1416             : #define ACTION_SELECTFIELD 2
    1417             : #define ACTION_EXPAND      3
    1418             : 
    1419           0 : long SentenceEditWindow_Impl::PreNotify( NotifyEvent& rNEvt )
    1420             : {
    1421           0 :     bool bChange = false;
    1422           0 :     const TextCharAttrib*  pErrorAttrib = 0;
    1423           0 :     if(rNEvt.GetType() == EVENT_KEYINPUT)
    1424             :     {
    1425           0 :         const KeyEvent& rKeyEvt = *rNEvt.GetKeyEvent();
    1426           0 :         bChange = TextEngine::DoesKeyChangeText( rKeyEvt );
    1427           0 :         if(bChange && !IsUndoEditMode() &&
    1428           0 :             rKeyEvt.GetKeyCode().GetCode() != KEY_TAB)
    1429             :         {
    1430           0 :             TextEngine* pTextEngine = GetTextEngine();
    1431           0 :             TextView* pTextView = pTextEngine->GetActiveView();
    1432           0 :             const TextSelection& rCurrentSelection = pTextView->GetSelection();
    1433             :             //determine if the selection contains a field
    1434           0 :             bool bHasField = false;
    1435           0 :             bool bHasError = false;
    1436           0 :             bool bHasFieldLeft = false;
    1437           0 :             bool bHasErrorLeft = false;
    1438             : 
    1439           0 :             bool bHasRange = rCurrentSelection.HasRange();
    1440           0 :             sal_uInt8 nSelectionType = 0; // invalid type!
    1441             : 
    1442           0 :             TextPaM aCursor(rCurrentSelection.GetStart());
    1443           0 :             const TextCharAttrib* pBackAttr = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_BACKGROUND );
    1444           0 :             const TextCharAttrib* pErrorAttr = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_ERROR );
    1445           0 :             const TextCharAttrib* pBackAttrLeft = 0;
    1446           0 :             const TextCharAttrib* pErrorAttrLeft = 0;
    1447             : 
    1448           0 :             bHasField = pBackAttr != 0 && (bHasRange || pBackAttr->GetEnd() > aCursor.GetIndex());
    1449           0 :             bHasError = pErrorAttr != 0 && (bHasRange || pErrorAttr->GetEnd() > aCursor.GetIndex());
    1450           0 :             if(bHasRange)
    1451             :             {
    1452           0 :                 if(pBackAttr &&
    1453           0 :                         pBackAttr->GetStart() == rCurrentSelection.GetStart().GetIndex() &&
    1454           0 :                         pBackAttr->GetEnd() == rCurrentSelection.GetEnd().GetIndex())
    1455             :                 {
    1456           0 :                     nSelectionType = FULL;
    1457             :                 }
    1458           0 :                 else if(pErrorAttr &&
    1459           0 :                         pErrorAttr->GetStart() <= rCurrentSelection.GetStart().GetIndex() &&
    1460           0 :                         pErrorAttr->GetEnd() >= rCurrentSelection.GetEnd().GetIndex())
    1461             :                 {
    1462           0 :                     nSelectionType = INSIDE_YES;
    1463             :                 }
    1464             :                 else
    1465             :                 {
    1466           0 :                     nSelectionType = bHasField||bHasError ? BRACE : OUTSIDE_NO;
    1467           0 :                     while(aCursor.GetIndex() < rCurrentSelection.GetEnd().GetIndex())
    1468             :                     {
    1469           0 :                         ++aCursor.GetIndex();
    1470           0 :                         const TextCharAttrib* pIntBackAttr = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_BACKGROUND );
    1471           0 :                         const TextCharAttrib* pIntErrorAttr = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_ERROR );
    1472             :                         //if any attr has been found then BRACE
    1473           0 :                         if(pIntBackAttr || pIntErrorAttr)
    1474           0 :                             nSelectionType = BRACE;
    1475             :                         //the field has to be selected
    1476           0 :                         if(pIntBackAttr && !pBackAttr)
    1477           0 :                             pBackAttr = pIntBackAttr;
    1478           0 :                         bHasField |= pIntBackAttr != 0;
    1479             :                     }
    1480             :                 }
    1481             :             }
    1482             :             else
    1483             :             {
    1484             :                 //no range selection: then 1 2 3 and 8 are possible
    1485           0 :                 const TextCharAttrib* pCurAttr = pBackAttr ? pBackAttr : pErrorAttr;
    1486           0 :                 if(pCurAttr)
    1487             :                 {
    1488           0 :                     nSelectionType = pCurAttr->GetStart() == rCurrentSelection.GetStart().GetIndex() ?
    1489           0 :                             LEFT_NO : pCurAttr->GetEnd() == rCurrentSelection.GetEnd().GetIndex() ? RIGHT_NO : INSIDE_NO;
    1490             :                 }
    1491             :                 else
    1492           0 :                     nSelectionType = OUTSIDE_NO;
    1493             : 
    1494           0 :                 bHasFieldLeft = pBackAttr && pBackAttr->GetEnd() == aCursor.GetIndex();
    1495           0 :                 if(bHasFieldLeft)
    1496             :                 {
    1497           0 :                     pBackAttrLeft = pBackAttr;
    1498           0 :                     pBackAttr = 0;
    1499             :                 }
    1500           0 :                 bHasErrorLeft = pErrorAttr && pErrorAttr->GetEnd() == aCursor.GetIndex();
    1501           0 :                 if(bHasErrorLeft)
    1502             :                 {
    1503           0 :                     pErrorAttrLeft = pErrorAttr;
    1504           0 :                     pErrorAttr = 0;
    1505             :                 }
    1506             : 
    1507             :                 //check previous position if this exists
    1508             :                 //that is a redundant in the case the the attribute found above already is on the left cursor side
    1509             :                 //but it's o.k. for two errors/fields side by side
    1510           0 :                 if(aCursor.GetIndex())
    1511             :                 {
    1512           0 :                     --aCursor.GetIndex();
    1513           0 :                     pBackAttrLeft = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_BACKGROUND );
    1514           0 :                     pErrorAttrLeft = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_ERROR );
    1515           0 :                     bHasFieldLeft = pBackAttrLeft !=0;
    1516           0 :                     bHasErrorLeft = pErrorAttrLeft != 0;
    1517           0 :                     ++aCursor.GetIndex();
    1518             :                 }
    1519             :             }
    1520             :             //Here we have to determine if the error found is the one currently active
    1521           0 :             bool bIsErrorActive = (pErrorAttr && pErrorAttr->GetStart() == m_nErrorStart) ||
    1522           0 :                     (pErrorAttrLeft && pErrorAttrLeft->GetStart() == m_nErrorStart);
    1523             : 
    1524             :             DBG_ASSERT(nSelectionType != INVALID, "selection type not set!");
    1525             : 
    1526           0 :             const KeyCode& rKeyCode = rKeyEvt.GetKeyCode();
    1527           0 :             bool bDelete = rKeyCode.GetCode() == KEY_DELETE;
    1528           0 :             bool bBackspace = rKeyCode.GetCode() == KEY_BACKSPACE;
    1529             : 
    1530           0 :             sal_Int8 nAction = ACTION_CONTINUE;
    1531           0 :             switch(nSelectionType)
    1532             :             {
    1533             : //    1 - backspace                   delete                      any other
    1534             : //        UE                          on field FS on error CO     on field FS on error CO
    1535             :                 case LEFT_NO    :
    1536           0 :                     if(bBackspace)
    1537             :                     {
    1538           0 :                         nAction = bHasFieldLeft ? ACTION_SELECTFIELD : ACTION_UNDOEDIT;
    1539             :                         //to force the use of pBackAttrLeft
    1540           0 :                         pBackAttr = 0;
    1541             :                     }
    1542           0 :                     else if(bDelete)
    1543           0 :                         nAction = bHasField ? ACTION_SELECTFIELD : ACTION_CONTINUE;
    1544             :                     else
    1545           0 :                         nAction = bHasError && !aCursor.GetIndex() ? ACTION_CONTINUE :
    1546           0 :                             bHasError ? ACTION_EXPAND : bHasErrorLeft ? ACTION_CONTINUE : ACTION_UNDOEDIT;
    1547           0 :                 break;
    1548             : //    2 - on field FS on error C
    1549             :                 case INSIDE_NO  :
    1550             :                     nAction =  bHasField ? ACTION_SELECTFIELD :
    1551           0 :                         bIsErrorActive ? ACTION_CONTINUE : ACTION_UNDOEDIT;
    1552           0 :                 break;
    1553             : //    3 - backspace                   delete                      any other
    1554             : //        on field FS on error CO     UE                          on field UE on error EX
    1555             :                 case RIGHT_NO   :
    1556           0 :                     if(bBackspace)
    1557           0 :                         nAction = bHasFieldLeft ? ACTION_SELECTFIELD : ACTION_CONTINUE;
    1558           0 :                     else if(bDelete)
    1559           0 :                         nAction = bHasFieldLeft && bHasError ? ACTION_CONTINUE : ACTION_UNDOEDIT;
    1560             :                     else
    1561             :                         nAction = bHasFieldLeft && bHasError ? ACTION_EXPAND :
    1562           0 :                             bHasError ? ACTION_CONTINUE : bHasErrorLeft ? ACTION_EXPAND :ACTION_UNDOEDIT;
    1563           0 :                 break;
    1564             : //    4 - on field UE and on error CO
    1565             :                 case FULL       :
    1566           0 :                     nAction = bHasField ? ACTION_UNDOEDIT : ACTION_CONTINUE;
    1567           0 :                 break;
    1568             : //    5 - on field FS and on error CO
    1569             :                 case INSIDE_YES :
    1570           0 :                     nAction = bHasField ? ACTION_SELECTFIELD : ACTION_CONTINUE;
    1571           0 :                 break;
    1572             : //    6 - on field FS and on error UE
    1573             :                 case BRACE      :
    1574           0 :                     nAction = bHasField ? ACTION_SELECTFIELD : ACTION_UNDOEDIT;;
    1575           0 :                 break;
    1576             : //    7 - UE
    1577             : //    8 - UE
    1578             :                 case OUTSIDE_NO :
    1579             :                 case OUTSIDE_YES:
    1580           0 :                     nAction = ACTION_UNDOEDIT;
    1581           0 :                 break;
    1582             :             }
    1583             :             //save the current paragraph
    1584           0 :             sal_uInt16 nCurrentLen = GetText().Len();
    1585           0 :             if(nAction != ACTION_SELECTFIELD)
    1586           0 :                 pTextView->GetWindow()->KeyInput(rKeyEvt);
    1587             :             else
    1588             :             {
    1589           0 :                 const TextCharAttrib* pCharAttr = pBackAttr ? pBackAttr : pBackAttrLeft;
    1590           0 :                 if(pCharAttr)
    1591             :                 {
    1592           0 :                     TextPaM aStart(0, pCharAttr->GetStart());
    1593           0 :                     TextPaM aEnd(0, pCharAttr->GetEnd());
    1594           0 :                     TextSelection aNewSel(aStart, aEnd);
    1595           0 :                     pTextView->SetSelection( aNewSel);
    1596             :                 }
    1597             :             }
    1598           0 :             if(nAction == ACTION_EXPAND)
    1599             :             {
    1600             :                 DBG_ASSERT(pErrorAttrLeft || pErrorAttr, "where is the error");
    1601             :                 //text has been added on the right and only the 'error attribute has to be corrected
    1602           0 :                 if(pErrorAttrLeft)
    1603             :                 {
    1604           0 :                     TextAttrib* pNewError =  pErrorAttrLeft->GetAttr().Clone();
    1605           0 :                     sal_uInt16 nStart = pErrorAttrLeft->GetStart();
    1606           0 :                     sal_uInt16 nEnd = pErrorAttrLeft->GetEnd();
    1607           0 :                     pTextEngine->RemoveAttrib( 0, *pErrorAttrLeft );
    1608           0 :                     SetAttrib( *pNewError, 0, nStart, ++nEnd );
    1609             :                     //only active errors move the mark
    1610           0 :                     if(bIsErrorActive)
    1611             :                     {
    1612           0 :                         bool bGrammar = static_cast<const SpellErrorAttrib&>(*pNewError).GetErrorDescription().bIsGrammarError;
    1613           0 :                         MoveErrorMarkTo(nStart, nEnd, bGrammar);
    1614             :                     }
    1615           0 :                     delete pNewError;
    1616             :                 }
    1617             :                 //text has been added on the left then the error attribute has to be expanded and the
    1618             :                 //field attribute on the right - if any - has to be contracted
    1619           0 :                 else if(pErrorAttr)
    1620             :                 {
    1621             :                     //determine the change
    1622           0 :                     sal_uInt16 nAddedChars = GetText().Len() - nCurrentLen;
    1623             : 
    1624           0 :                     TextAttrib* pNewError =  pErrorAttr->GetAttr().Clone();
    1625           0 :                     sal_uInt16 nStart = pErrorAttr->GetStart();
    1626           0 :                     sal_uInt16 nEnd = pErrorAttr->GetEnd();
    1627           0 :                     pTextEngine->RemoveAttrib( 0, *pErrorAttr );
    1628           0 :                     nStart = nStart - (sal_uInt16)nAddedChars;
    1629           0 :                     SetAttrib( *pNewError, 0, nStart - nAddedChars, nEnd );
    1630             :                     //only if the error is active the mark is moved here
    1631           0 :                     if(bIsErrorActive)
    1632             :                     {
    1633           0 :                         bool bGrammar = static_cast<const SpellErrorAttrib&>(*pNewError).GetErrorDescription().bIsGrammarError;
    1634           0 :                         MoveErrorMarkTo(nStart, nEnd, bGrammar);
    1635             :                     }
    1636           0 :                     delete pNewError;
    1637             : 
    1638           0 :                     if(pBackAttrLeft)
    1639             :                     {
    1640           0 :                         TextAttrib* pNewBack =  pBackAttrLeft->GetAttr().Clone();
    1641           0 :                         sal_uInt16 _nStart = pBackAttrLeft->GetStart();
    1642           0 :                         sal_uInt16 _nEnd = pBackAttrLeft->GetEnd();
    1643           0 :                         pTextEngine->RemoveAttrib( 0, *pBackAttrLeft );
    1644           0 :                         SetAttrib( *pNewBack, 0, _nStart, _nEnd - nAddedChars);
    1645           0 :                         delete pNewBack;
    1646             :                     }
    1647             :                 }
    1648             :             }
    1649           0 :             else if(nAction == ACTION_UNDOEDIT)
    1650             :             {
    1651           0 :                 SetUndoEditMode(true);
    1652             :             }
    1653             :             //make sure the error positions are correct after text changes
    1654             :             //the old attribute may have been deleted
    1655             :             //all changes inside of the current error leave the error attribute at the current
    1656             :             //start position
    1657           0 :             if(!IsUndoEditMode() && bIsErrorActive)
    1658             :             {
    1659           0 :                 const TextCharAttrib* pFontColor = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_FONTCOLOR );
    1660           0 :                 pErrorAttrib = pTextEngine->FindCharAttrib( TextPaM(0, m_nErrorStart), TEXTATTR_SPELL_ERROR );
    1661           0 :                 if(pFontColor && pErrorAttrib )
    1662             :                 {
    1663           0 :                     m_nErrorStart = pFontColor->GetStart();
    1664           0 :                     m_nErrorEnd = pFontColor->GetEnd();
    1665           0 :                     if(pErrorAttrib->GetStart() != m_nErrorStart || pErrorAttrib->GetEnd() != m_nErrorEnd)
    1666             :                     {
    1667           0 :                         TextAttrib* pNewError =  pErrorAttrib->GetAttr().Clone();
    1668           0 :                         pTextEngine->RemoveAttrib( 0, *pErrorAttr );
    1669           0 :                         SetAttrib( *pNewError, 0, m_nErrorStart, m_nErrorEnd );
    1670           0 :                         delete pNewError;
    1671             :                     }
    1672             :                 }
    1673             :             }
    1674             :             //this is not a modification anymore
    1675           0 :             if(nAction != ACTION_SELECTFIELD && !m_bIsUndoEditMode)
    1676           0 :                 CallModifyLink();
    1677             :         }
    1678             :         else
    1679           0 :             bChange = false;
    1680             :     }
    1681           0 :     long nRet = bChange ? 1 : MultiLineEdit::PreNotify(rNEvt);
    1682           0 :     return nRet;
    1683             : }
    1684             : 
    1685             : //-----------------------------------------------------------------------
    1686           0 : bool SentenceEditWindow_Impl::MarkNextError( bool bIgnoreCurrentError )
    1687             : {
    1688           0 :     if (bIgnoreCurrentError)
    1689           0 :         m_aIgnoreErrorsAt.insert( m_nErrorStart );
    1690           0 :     ExtTextEngine* pTextEngine = GetTextEngine();
    1691           0 :     sal_uInt16 nTextLen = pTextEngine->GetTextLen(0);
    1692           0 :     if(m_nErrorEnd >= nTextLen - 1)
    1693           0 :         return false;
    1694             :     //if it's not already modified the modified flag has to be reset at the and of the marking
    1695           0 :     bool bModified = IsModified();
    1696           0 :     bool bRet = false;
    1697           0 :     const sal_uInt16 nOldErrorStart = m_nErrorStart;
    1698           0 :     const sal_uInt16 nOldErrorEnd   = m_nErrorEnd;
    1699             : 
    1700             :     //create a cursor behind the end of the last error
    1701             :     //- or at 0 at the start of the sentence
    1702           0 :     TextPaM aCursor(0, m_nErrorEnd ? m_nErrorEnd + 1 : 0);
    1703             :     //search for SpellErrorAttrib
    1704             : 
    1705           0 :     const TextCharAttrib* pNextError = 0;
    1706             :     //iterate over the text and search for the next error that maybe has
    1707             :     //to be replace by a ChangeAllList replacement
    1708           0 :     bool bGrammarError = false;
    1709           0 :     while(aCursor.GetIndex() < nTextLen)
    1710             :     {
    1711           0 :         while(aCursor.GetIndex() < nTextLen &&
    1712           0 :                 0 == (pNextError = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_ERROR)))
    1713             :         {
    1714           0 :             ++aCursor.GetIndex();
    1715             :         }
    1716             :         // maybe the error found here is already in the ChangeAllList and has to be replaced
    1717             : 
    1718           0 :         Reference<XDictionary> xChangeAll( SvxGetChangeAllList(), UNO_QUERY );
    1719           0 :         Reference<XDictionaryEntry> xEntry;
    1720             : 
    1721           0 :         const SpellErrorDescription* pSpellErrorDescription = 0;
    1722           0 :         if(pNextError)
    1723             :         {
    1724           0 :             pSpellErrorDescription = &static_cast<const SpellErrorAttrib&>(pNextError->GetAttr()).GetErrorDescription();
    1725           0 :             bGrammarError = pSpellErrorDescription->bIsGrammarError;
    1726             :         }
    1727           0 :         if(xChangeAll->getCount() && pSpellErrorDescription &&
    1728           0 :                 (xEntry = xChangeAll->getEntry( pSpellErrorDescription->sErrorText )).is())
    1729             :         {
    1730           0 :             m_nErrorStart = pNextError->GetStart();
    1731           0 :             m_nErrorEnd = pNextError->GetEnd();
    1732             : 
    1733           0 :             String sReplacement(getDotReplacementString(GetErrorText(), xEntry->getReplacementText()));
    1734             : 
    1735           0 :             ChangeMarkedWord(sReplacement, LanguageTag( pSpellErrorDescription->aLocale ).getLanguageType());
    1736             : 
    1737           0 :             aCursor.GetIndex() = aCursor.GetIndex() + (sal_uInt16)(xEntry->getReplacementText().getLength());
    1738             :         }
    1739             :         else
    1740             :             break;
    1741           0 :     }
    1742             : 
    1743             :     //if an attrib has been found search for the end of the error string
    1744           0 :     if(aCursor.GetIndex() < nTextLen)
    1745             :     {
    1746           0 :         m_nErrorStart = aCursor.GetIndex();
    1747           0 :         m_nErrorEnd = pNextError->GetEnd();
    1748           0 :         MoveErrorMarkTo(m_nErrorStart, m_nErrorEnd, bGrammarError);
    1749           0 :         bRet = true;
    1750             :         //add an undo action
    1751             :         SpellUndoAction_Impl* pAction = new SpellUndoAction_Impl(
    1752           0 :                 SPELLUNDO_CHANGE_NEXTERROR, GetSpellDialog()->aDialogUndoLink);
    1753           0 :         pAction->SetErrorMove(m_nErrorStart, m_nErrorEnd, nOldErrorStart, nOldErrorEnd);
    1754             :         const SpellErrorAttrib* pOldAttrib = static_cast<const SpellErrorAttrib*>(
    1755           0 :                 pTextEngine->FindAttrib( TextPaM(0, nOldErrorStart), TEXTATTR_SPELL_ERROR ));
    1756           0 :         pAction->SetErrorLanguageSelected(pOldAttrib && pOldAttrib->GetErrorDescription().aSuggestions.getLength() &&
    1757           0 :                 LanguageTag( pOldAttrib->GetErrorDescription().aLocale).getLanguageType() ==
    1758           0 :                                         GetSpellDialog()->aLanguageLB.GetSelectLanguage());
    1759           0 :         AddUndoAction(pAction);
    1760             :     }
    1761             :     else
    1762           0 :         m_nErrorStart = m_nErrorEnd = nTextLen;
    1763           0 :     if( !bModified )
    1764           0 :         ClearModifyFlag();
    1765           0 :     SpellDialog* pSpellDialog = GetSpellDialog();
    1766           0 :     pSpellDialog->aIgnorePB.Enable(bRet);
    1767           0 :     pSpellDialog->aIgnoreAllPB.Enable(bRet);
    1768           0 :     pSpellDialog->aAutoCorrPB.Enable(bRet);
    1769           0 :     pSpellDialog->aAddToDictMB.Enable(bRet);
    1770           0 :     pSpellDialog->aAddToDictPB.Enable(bRet);
    1771           0 :     return bRet;
    1772             : }
    1773             : 
    1774             : //-----------------------------------------------------------------------
    1775           0 : void SentenceEditWindow_Impl::MoveErrorMarkTo(sal_uInt16 nStart, sal_uInt16 nEnd, bool bGrammarError)
    1776             : {
    1777           0 :     TextEngine* pTextEngine = GetTextEngine();
    1778           0 :     pTextEngine->RemoveAttribs( 0, (sal_uInt16)TEXTATTR_FONTCOLOR, sal_True );
    1779           0 :     pTextEngine->RemoveAttribs( 0, (sal_uInt16)TEXTATTR_FONTWEIGHT, sal_True );
    1780           0 :     pTextEngine->SetAttrib( TextAttribFontWeight(WEIGHT_BOLD), 0, nStart, nEnd );
    1781           0 :     pTextEngine->SetAttrib( TextAttribFontColor(bGrammarError ? COL_LIGHTBLUE : COL_LIGHTRED), 0, nStart, nEnd );
    1782           0 :     m_nErrorStart = nStart;
    1783           0 :     m_nErrorEnd = nEnd;
    1784           0 : }
    1785             : 
    1786             : //-----------------------------------------------------------------------
    1787           0 : void SentenceEditWindow_Impl::ChangeMarkedWord(const String& rNewWord, LanguageType eLanguage)
    1788             : {
    1789             :     //calculate length changes
    1790           0 :     long nDiffLen = rNewWord.Len() - m_nErrorEnd + m_nErrorStart;
    1791           0 :     TextSelection aSel(TextPaM(0, m_nErrorStart), TextPaM(0, m_nErrorEnd));
    1792             :     //Remove spell errror attribute
    1793           0 :     ExtTextEngine* pTextEngine = GetTextEngine();
    1794           0 :     pTextEngine->UndoActionStart();
    1795           0 :     const TextCharAttrib*  pErrorAttrib = pTextEngine->FindCharAttrib( TextPaM(0, m_nErrorStart), TEXTATTR_SPELL_ERROR );
    1796             :     DBG_ASSERT(pErrorAttrib, "no error attribute found");
    1797           0 :     const SpellErrorDescription* pSpellErrorDescription = 0;
    1798           0 :     if(pErrorAttrib)
    1799             :     {
    1800           0 :         pTextEngine->RemoveAttrib(0, *pErrorAttrib);
    1801           0 :         pSpellErrorDescription = &static_cast<const SpellErrorAttrib&>(pErrorAttrib->GetAttr()).GetErrorDescription();
    1802             :     }
    1803           0 :     const TextCharAttrib*  pBackAttrib = pTextEngine->FindCharAttrib( TextPaM(0, m_nErrorStart), TEXTATTR_SPELL_BACKGROUND );
    1804           0 :     pTextEngine->ReplaceText( aSel, rNewWord );
    1805             : 
    1806           0 :     if(!m_nErrorStart)
    1807             :     {
    1808             :         //attributes following an error at the start of the text are not moved but expanded from the
    1809             :         //text engine - this is done to keep full-paragraph-attributes
    1810             :         //in the current case that handling is not desired
    1811             :         const TextCharAttrib*  pLangAttrib =
    1812             :                 pTextEngine->FindCharAttrib(
    1813           0 :                     TextPaM(0, m_nErrorEnd), TEXTATTR_SPELL_LANGUAGE );
    1814           0 :         sal_uInt16 nTextLen = pTextEngine->GetTextLen( 0 );
    1815           0 :         if(pLangAttrib && !pLangAttrib->GetStart() && pLangAttrib->GetEnd() ==
    1816             :             nTextLen)
    1817             :         {
    1818           0 :             SpellLanguageAttrib aNewLangAttrib( static_cast<const SpellLanguageAttrib&>(pLangAttrib->GetAttr()).GetLanguage());
    1819           0 :             pTextEngine->RemoveAttrib(0, *pLangAttrib);
    1820           0 :             pTextEngine->SetAttrib( aNewLangAttrib, 0, (sal_uInt16)(m_nErrorEnd + nDiffLen) , nTextLen );
    1821             :         }
    1822             :     }
    1823             :     // undo expanded attributes!
    1824           0 :     if( pBackAttrib && pBackAttrib->GetStart() < m_nErrorStart && pBackAttrib->GetEnd() == m_nErrorEnd + nDiffLen)
    1825             :     {
    1826           0 :         TextAttrib* pNewBackground = pBackAttrib->GetAttr().Clone();
    1827           0 :         sal_uInt16 nStart = pBackAttrib->GetStart();
    1828           0 :         pTextEngine->RemoveAttrib(0, *pBackAttrib);
    1829           0 :         pTextEngine->SetAttrib(*pNewBackground, 0, nStart, m_nErrorStart);
    1830           0 :         delete pNewBackground;
    1831             :     }
    1832           0 :     pTextEngine->SetModified(sal_True);
    1833             : 
    1834             :     //adjust end position
    1835           0 :     long nEndTemp = m_nErrorEnd;
    1836           0 :     nEndTemp += nDiffLen;
    1837           0 :     m_nErrorEnd = (sal_uInt16)nEndTemp;
    1838             : 
    1839             :     SpellUndoAction_Impl* pAction = new SpellUndoAction_Impl(
    1840           0 :                     SPELLUNDO_MOVE_ERROREND, GetSpellDialog()->aDialogUndoLink);
    1841           0 :     pAction->SetOffset(nDiffLen);
    1842           0 :     AddUndoAction(pAction);
    1843           0 :     if(pSpellErrorDescription)
    1844           0 :         SetAttrib( SpellErrorAttrib(*pSpellErrorDescription), 0, m_nErrorStart, m_nErrorEnd );
    1845           0 :     SetAttrib( SpellLanguageAttrib(eLanguage), 0, m_nErrorStart, m_nErrorEnd );
    1846           0 :     pTextEngine->UndoActionEnd();
    1847           0 : }
    1848             : 
    1849             : //-------------------------------------------------
    1850           0 : String SentenceEditWindow_Impl::GetErrorText() const
    1851             : {
    1852           0 :     return GetTextEngine()->GetText(TextSelection(TextPaM(0, m_nErrorStart), TextPaM(0, m_nErrorEnd) ));
    1853             : }
    1854             : 
    1855             : //-----------------------------------------------------------------------
    1856           0 : const SpellErrorDescription* SentenceEditWindow_Impl::GetAlternatives()
    1857             : {
    1858           0 :     TextPaM aCursor(0, m_nErrorStart);
    1859             :     const SpellErrorAttrib* pAttrib = static_cast<const SpellErrorAttrib*>(
    1860           0 :             GetTextEngine()->FindAttrib( aCursor, TEXTATTR_SPELL_ERROR));
    1861           0 :     return pAttrib ? &pAttrib->GetErrorDescription() : 0;
    1862             : }
    1863             : 
    1864             : //-----------------------------------------------------------------------
    1865           0 : void SentenceEditWindow_Impl::RestoreCurrentError()
    1866             : {
    1867           0 :     TextPaM aCursor(0, m_nErrorStart);
    1868             :     const SpellErrorAttrib* pAttrib = static_cast<const SpellErrorAttrib*>(
    1869           0 :             GetTextEngine()->FindAttrib( aCursor, TEXTATTR_SPELL_ERROR));
    1870           0 :     if( pAttrib )
    1871             :     {
    1872           0 :         const SpellErrorDescription& rDesc = pAttrib->GetErrorDescription();
    1873           0 :         if( !rDesc.sErrorText.equals( GetErrorText() ) )
    1874           0 :             ChangeMarkedWord(rDesc.sErrorText, LanguageTag( rDesc.aLocale ).getLanguageType());
    1875             :     }
    1876           0 : }
    1877             : 
    1878             : //-----------------------------------------------------------------------
    1879           0 : void SentenceEditWindow_Impl::SetAlternatives( Reference< XSpellAlternatives> xAlt )
    1880             : {
    1881           0 :     TextPaM aCursor(0, m_nErrorStart);
    1882             :     DBG_ASSERT(static_cast<const SpellErrorAttrib*>(
    1883             :             GetTextEngine()->FindAttrib( aCursor, TEXTATTR_SPELL_ERROR)), "no error set?");
    1884             : 
    1885           0 :     ::rtl::OUString aWord;
    1886           0 :     lang::Locale    aLocale;
    1887           0 :     uno::Sequence< ::rtl::OUString >    aAlts;
    1888           0 :     ::rtl::OUString sServiceName;
    1889           0 :     if (xAlt.is())
    1890             :     {
    1891           0 :         aWord   = xAlt->getWord();
    1892           0 :         aLocale = xAlt->getLocale();
    1893           0 :         aAlts   = xAlt->getAlternatives();
    1894           0 :         uno::Reference< container::XNamed > xNamed( xAlt, uno::UNO_QUERY );
    1895           0 :         if (xNamed.is())
    1896           0 :             sServiceName = xNamed->getName();
    1897             :     }
    1898           0 :     SpellErrorDescription aDesc( false, aWord, aLocale, aAlts, 0, sServiceName);
    1899           0 :     GetTextEngine()->SetAttrib( SpellErrorAttrib(aDesc), 0, m_nErrorStart, m_nErrorEnd );
    1900           0 : }
    1901             : 
    1902             : //-----------------------------------------------------------------------
    1903           0 : void SentenceEditWindow_Impl::SetAttrib( const TextAttrib& rAttr, sal_uLong nPara, sal_uInt16 nStart, sal_uInt16 nEnd )
    1904             : {
    1905           0 :     GetTextEngine()->SetAttrib(rAttr, nPara, nStart, nEnd);
    1906           0 : }
    1907             : 
    1908             : //-----------------------------------------------------------------------
    1909           0 : void SentenceEditWindow_Impl::SetText( const String& rStr )
    1910             : {
    1911           0 :     m_nErrorStart = m_nErrorEnd = 0;
    1912           0 :     GetTextEngine()->SetText(rStr);
    1913           0 : }
    1914             : 
    1915             : //-----------------------------------------------------------------------
    1916             : struct LanguagePosition_Impl
    1917             : {
    1918             :     sal_uInt16          nPosition;
    1919             :     LanguageType    eLanguage;
    1920             : 
    1921           0 :     LanguagePosition_Impl(sal_uInt16 nPos, LanguageType eLang) :
    1922             :         nPosition(nPos),
    1923           0 :         eLanguage(eLang)
    1924           0 :         {}
    1925             : };
    1926             : typedef std::vector<LanguagePosition_Impl> LanguagePositions_Impl;
    1927             : 
    1928           0 : static void lcl_InsertBreakPosition_Impl(
    1929             :         LanguagePositions_Impl& rBreakPositions, sal_uInt16 nInsert, LanguageType eLanguage)
    1930             : {
    1931           0 :     LanguagePositions_Impl::iterator aStart = rBreakPositions.begin();
    1932           0 :     while(aStart != rBreakPositions.end())
    1933             :     {
    1934           0 :         if(aStart->nPosition == nInsert)
    1935             :         {
    1936             :             //the language of following starts has to overwrite
    1937             :             //the one of previous ends
    1938           0 :             aStart->eLanguage = eLanguage;
    1939             :             return;
    1940             :         }
    1941           0 :         else if(aStart->nPosition > nInsert)
    1942             :         {
    1943             : 
    1944           0 :             rBreakPositions.insert(aStart, LanguagePosition_Impl(nInsert, eLanguage));
    1945             :             return;
    1946             :         }
    1947             :         else
    1948           0 :             ++aStart;
    1949             :     }
    1950           0 :     rBreakPositions.push_back(LanguagePosition_Impl(nInsert, eLanguage));
    1951             : }
    1952             : /*-------------------------------------------------------------------------
    1953             :     Returns the text in spell portions. Each portion contains text with an
    1954             :     equal language and attribute. The spell alternatives are empty.
    1955             :   -----------------------------------------------------------------------*/
    1956           0 : svx::SpellPortions SentenceEditWindow_Impl::CreateSpellPortions( bool bSetIgnoreFlag ) const
    1957             : {
    1958           0 :     svx::SpellPortions aRet;
    1959           0 :     ExtTextEngine* pTextEngine = GetTextEngine();
    1960           0 :     const sal_uInt16 nTextLen = pTextEngine->GetTextLen(0);
    1961           0 :     if(nTextLen)
    1962             :     {
    1963           0 :         TextPaM aCursor(0, 0);
    1964           0 :         LanguagePositions_Impl aBreakPositions;
    1965           0 :         const TextCharAttrib* pLastLang = 0;
    1966           0 :         const TextCharAttrib* pLastError = 0;
    1967           0 :         LanguageType eLang = LANGUAGE_DONTKNOW;
    1968           0 :         const TextCharAttrib* pError = 0;
    1969           0 :         while(aCursor.GetIndex() < nTextLen)
    1970             :         {
    1971           0 :             const TextCharAttrib* pLang = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_LANGUAGE);
    1972           0 :             if(pLang && pLang != pLastLang)
    1973             :             {
    1974           0 :                 eLang = static_cast<const SpellLanguageAttrib&>(pLang->GetAttr()).GetLanguage();
    1975           0 :                 lcl_InsertBreakPosition_Impl(aBreakPositions, pLang->GetStart(), eLang);
    1976           0 :                 lcl_InsertBreakPosition_Impl(aBreakPositions, pLang->GetEnd(), eLang);
    1977           0 :                 pLastLang = pLang;
    1978             :             }
    1979           0 :             pError = pTextEngine->FindCharAttrib( aCursor, TEXTATTR_SPELL_ERROR);
    1980           0 :             if(pError && pLastError != pError)
    1981             :             {
    1982           0 :                 lcl_InsertBreakPosition_Impl(aBreakPositions, pError->GetStart(), eLang);
    1983           0 :                 lcl_InsertBreakPosition_Impl(aBreakPositions, pError->GetEnd(), eLang);
    1984           0 :                 pLastError = pError;
    1985             : 
    1986             :             }
    1987           0 :             aCursor.GetIndex()++;
    1988             :         }
    1989             : 
    1990           0 :         if(nTextLen && aBreakPositions.empty())
    1991             :         {
    1992             :             //if all content has been overwritten the attributes may have been removed, too
    1993           0 :             svx::SpellPortion aPortion1;
    1994           0 :             aPortion1.eLanguage = GetSpellDialog()->GetSelectedLang_Impl();
    1995             :             aPortion1.sText = pTextEngine->GetText(
    1996           0 :                         TextSelection(TextPaM(0, 0), TextPaM(0, nTextLen)));
    1997             : 
    1998           0 :             aRet.push_back(aPortion1);
    1999             : 
    2000             :         }
    2001           0 :         else if(!aBreakPositions.empty())
    2002             :         {
    2003           0 :             LanguagePositions_Impl::iterator aStart = aBreakPositions.begin();
    2004             :             //start should always be Null
    2005           0 :             eLang = aStart->eLanguage;
    2006           0 :             sal_uInt16 nStart = aStart->nPosition;
    2007             :             DBG_ASSERT(!nStart, "invalid start position - language attribute missing?");
    2008           0 :             ++aStart;
    2009             : 
    2010           0 :             while(aStart != aBreakPositions.end())
    2011             :             {
    2012           0 :                 svx::SpellPortion aPortion1;
    2013           0 :                 aPortion1.eLanguage = eLang;
    2014             :                 aPortion1.sText = pTextEngine->GetText(
    2015           0 :                             TextSelection(TextPaM(0, nStart), TextPaM(0, aStart->nPosition)));
    2016           0 :                 bool bIsIgnoreError = m_aIgnoreErrorsAt.find( nStart ) != m_aIgnoreErrorsAt.end();
    2017           0 :                 if( bSetIgnoreFlag && bIsIgnoreError )
    2018             :                 {
    2019           0 :                     aPortion1.bIgnoreThisError = true;
    2020             :                 }
    2021           0 :                 aRet.push_back(aPortion1);
    2022           0 :                 nStart = aStart->nPosition;
    2023           0 :                 eLang = aStart->eLanguage;
    2024           0 :                 ++aStart;
    2025           0 :             }
    2026             :         }
    2027             : 
    2028             :         // quick partly fix of #i71318. Correct fix needs to patch the TextEngine itself...
    2029             :         // this one will only prevent text from disappearing. It may to not have the
    2030             :         // correct language and will probably not spell checked...
    2031           0 :         sal_uLong nPara = pTextEngine->GetParagraphCount();
    2032           0 :         if (nPara > 1)
    2033             :         {
    2034           0 :             String aLeftOverText;
    2035           0 :             for (sal_uLong i = 1;  i < nPara;  ++i)
    2036             :             {
    2037           0 :                 aLeftOverText.AppendAscii( "\x0a" );    // the manual line break...
    2038           0 :                 aLeftOverText += pTextEngine->GetText(i);
    2039             :             }
    2040           0 :             if (pError)
    2041             :             {   // we need to add a new portion containing the left-over text
    2042           0 :                 svx::SpellPortion aPortion2;
    2043           0 :                 aPortion2.eLanguage = eLang;
    2044           0 :                 aPortion2.sText = aLeftOverText;
    2045           0 :                 aRet.push_back( aPortion2 );
    2046             :             }
    2047             :             else
    2048             :             {   // we just need to append the left-over text to the last portion (which had no errors)
    2049           0 :                 aRet[ aRet.size() - 1 ].sText += aLeftOverText;
    2050           0 :             }
    2051           0 :         }
    2052             :    }
    2053           0 :     return aRet;
    2054             : }
    2055             : 
    2056             : //-----------------------------------------------------------------------
    2057           0 : void SentenceEditWindow_Impl::Undo()
    2058             : {
    2059           0 :     ::svl::IUndoManager& rUndoMgr = GetTextEngine()->GetUndoManager();
    2060             :     DBG_ASSERT(GetUndoActionCount(), "no undo actions available" );
    2061           0 :     if(!GetUndoActionCount())
    2062           0 :         return;
    2063           0 :     bool bSaveUndoEdit = IsUndoEditMode();
    2064             :     sal_uInt16 nId;
    2065             :     //if the undo edit mode is active then undo all changes until the UNDO_EDIT_MODE action has been found
    2066           0 :     do
    2067             :     {
    2068           0 :         nId = rUndoMgr.GetUndoActionId();
    2069           0 :         rUndoMgr.Undo();
    2070           0 :     }while(bSaveUndoEdit && SPELLUNDO_UNDO_EDIT_MODE != nId && GetUndoActionCount());
    2071             : 
    2072           0 :     if(bSaveUndoEdit || SPELLUNDO_CHANGE_GROUP == nId)
    2073           0 :         GetSpellDialog()->UpdateBoxes_Impl();
    2074             : }
    2075             : 
    2076             : //-----------------------------------------------------------------------
    2077           0 : void SentenceEditWindow_Impl::ResetUndo()
    2078             : {
    2079           0 :     GetTextEngine()->ResetUndo();
    2080           0 : }
    2081             : 
    2082             : //-----------------------------------------------------------------------
    2083           0 : void SentenceEditWindow_Impl::AddUndoAction( SfxUndoAction *pAction, sal_Bool bTryMerg )
    2084             : {
    2085           0 :     ::svl::IUndoManager& rUndoMgr = GetTextEngine()->GetUndoManager();
    2086           0 :     rUndoMgr.AddUndoAction(pAction, bTryMerg);
    2087           0 :     GetSpellDialog()->aUndoPB.Enable();
    2088           0 : }
    2089             : 
    2090             : //-----------------------------------------------------------------------
    2091           0 : sal_uInt16 SentenceEditWindow_Impl::GetUndoActionCount()
    2092             : {
    2093           0 :     return GetTextEngine()->GetUndoManager().GetUndoActionCount();
    2094             : }
    2095             : 
    2096             : //-----------------------------------------------------------------------
    2097           0 : void SentenceEditWindow_Impl::UndoActionStart( sal_uInt16 nId )
    2098             : {
    2099           0 :     GetTextEngine()->UndoActionStart(nId);
    2100           0 : }
    2101             : 
    2102             : //-----------------------------------------------------------------------
    2103           0 : void SentenceEditWindow_Impl::UndoActionEnd()
    2104             : {
    2105           0 :     GetTextEngine()->UndoActionEnd();
    2106           0 : }
    2107             : 
    2108             : //-----------------------------------------------------------------------
    2109           0 : void SentenceEditWindow_Impl::MoveErrorEnd(long nOffset)
    2110             : {
    2111           0 :     if(nOffset > 0)
    2112           0 :         m_nErrorEnd = m_nErrorEnd - (sal_uInt16)nOffset;
    2113             :     else
    2114           0 :         m_nErrorEnd = m_nErrorEnd -(sal_uInt16)- nOffset;
    2115           0 : }
    2116             : 
    2117             : //-----------------------------------------------------------------------
    2118           0 : void  SentenceEditWindow_Impl::SetUndoEditMode(bool bSet)
    2119             : {
    2120             :     DBG_ASSERT(!bSet || m_bIsUndoEditMode != bSet, "SetUndoEditMode with equal values?");
    2121           0 :     m_bIsUndoEditMode = bSet;
    2122             :     //disable all buttons except the Change
    2123           0 :     SpellDialog* pSpellDialog = GetSpellDialog();
    2124             :     Control* aControls[] =
    2125             :     {
    2126             :         &pSpellDialog->aChangeAllPB,
    2127             :         &pSpellDialog->aExplainFT,
    2128             :         &pSpellDialog->aIgnoreAllPB,
    2129             :         &pSpellDialog->aIgnoreRulePB,
    2130             :         &pSpellDialog->aIgnorePB,
    2131             :         &pSpellDialog->aSuggestionLB,
    2132             :         &pSpellDialog->aSuggestionFT,
    2133             :         &pSpellDialog->aLanguageFT,
    2134             :         &pSpellDialog->aLanguageLB,
    2135             :         &pSpellDialog->aAddToDictMB,
    2136             :         &pSpellDialog->aAddToDictPB,
    2137             :         &pSpellDialog->aAutoCorrPB,
    2138             :         0
    2139           0 :     };
    2140           0 :     sal_Int32 nIdx = 0;
    2141           0 :     do
    2142             :     {
    2143           0 :         aControls[nIdx]->Enable(sal_False);
    2144             :     }
    2145           0 :     while(aControls[++nIdx]);
    2146             : 
    2147             :     //remove error marks
    2148           0 :     TextEngine* pTextEngine = GetTextEngine();
    2149           0 :     pTextEngine->RemoveAttribs( 0, (sal_uInt16)TEXTATTR_FONTCOLOR, sal_True );
    2150           0 :     pTextEngine->RemoveAttribs( 0, (sal_uInt16)TEXTATTR_FONTWEIGHT, sal_True );
    2151             : 
    2152             :     //put the appropriate action on the Undo-stack
    2153             :     SpellUndoAction_Impl* pAction = new SpellUndoAction_Impl(
    2154           0 :                         SPELLUNDO_UNDO_EDIT_MODE, GetSpellDialog()->aDialogUndoLink);
    2155           0 :     AddUndoAction(pAction);
    2156           0 :     pSpellDialog->aChangePB.Enable();
    2157           0 : }
    2158             : 
    2159           0 : IMPL_LINK( SpellDialog, HandleHyperlink, FixedHyperlink*, pHyperlink )
    2160             : {
    2161           0 :     rtl::OUString sURL=pHyperlink->GetURL();
    2162           0 :     rtl::OUString sTitle=GetText();
    2163             : 
    2164           0 :     if ( sURL.isEmpty() ) // Nothing to do, when the URL is empty
    2165           0 :         return 1;
    2166             :     try
    2167             :     {
    2168             :         uno::Reference< com::sun::star::system::XSystemShellExecute > xSystemShellExecute(
    2169           0 :             com::sun::star::system::SystemShellExecute::create(::comphelper::getProcessComponentContext()) );
    2170           0 :         xSystemShellExecute->execute( sURL, rtl::OUString(), com::sun::star::system::SystemShellExecuteFlags::URIS_ONLY );
    2171             :     }
    2172           0 :     catch ( uno::Exception& )
    2173             :     {
    2174           0 :         uno::Any exc( ::cppu::getCaughtException() );
    2175           0 :         rtl::OUString msg( ::comphelper::anyToString( exc ) );
    2176           0 :         const SolarMutexGuard guard;
    2177           0 :         ErrorBox aErrorBox( NULL, WB_OK, msg );
    2178           0 :         aErrorBox.SetText( sTitle );
    2179           0 :         aErrorBox.Execute();
    2180             :     }
    2181             : 
    2182           0 :     return 1;
    2183           6 : }
    2184             : 
    2185             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10