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