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