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