1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <SwSpellDialogChildWindow.hxx>
22 #include <vcl/svapp.hxx>
23 #include <vcl/weld.hxx>
24 #include <editeng/svxacorr.hxx>
25 #include <editeng/acorrcfg.hxx>
26 #include <sfx2/bindings.hxx>
27 #include <sfx2/dispatch.hxx>
28 #include <sfx2/viewfrm.hxx>
30 #include <sfx2/printer.hxx>
31 #include <svx/svdoutl.hxx>
32 #include <svx/svdview.hxx>
33 #include <unotools/linguprops.hxx>
34 #include <unotools/lingucfg.hxx>
35 #include <osl/diagnose.h>
37 #include <IDocumentDeviceAccess.hxx>
38 #include <IDocumentDrawModelAccess.hxx>
40 #include <drawdoc.hxx>
41 #include <dcontact.hxx>
44 #include <drawbase.hxx>
45 #include <unotextrange.hxx>
46 #include <strings.hrc>
49 using namespace ::com::sun::star
;
50 using namespace ::com::sun::star::uno
;
51 using namespace ::com::sun::star::text
;
52 using namespace ::com::sun::star::linguistic2
;
53 using namespace ::com::sun::star::beans
;
55 SFX_IMPL_CHILDWINDOW_WITHID(SwSpellDialogChildWindow
, FN_SPELL_GRAMMAR_DIALOG
)
60 bool m_bLockFocus
; // lock the focus notification while a modal dialog is active
63 // restart and progress information
64 bool m_bBodySpelled
; // body already spelled
65 bool m_bOtherSpelled
; // frames, footnotes, headers and footers spelled
66 bool m_bStartedInOther
; // started the spelling inside of the _other_ area
67 bool m_bStartedInSelection
; // there was an initial text selection
68 std::unique_ptr
<SwPaM
>
69 pOtherCursor
; // position where the spelling inside the _other_ area started
70 bool m_bDrawingsSpelled
; // all drawings spelled
71 Reference
<XTextRange
> m_xStartRange
; // text range that marks the start of spelling
72 const SdrObject
* m_pStartDrawing
; // draw text object spelling started in
73 ESelection m_aStartDrawingSelection
; // draw text start selection
74 bool m_bRestartDrawing
; // the first selected drawing object is found again
76 // lose/get focus information to decide if spelling can be continued
78 const SwNode
* m_pPointNode
;
79 const SwNode
* m_pMarkNode
;
80 sal_Int32 m_nPointPos
;
82 const SdrOutliner
* m_pOutliner
;
83 ESelection m_aESelection
;
85 // iterating over draw text objects
86 std::list
<SdrTextObj
*> m_aTextObjects
;
87 bool m_bTextObjectsCollected
;
93 m_bBodySpelled(false),
94 m_bOtherSpelled(false),
95 m_bStartedInOther(false),
96 m_bStartedInSelection(false),
97 m_bDrawingsSpelled(false),
98 m_pStartDrawing(nullptr),
99 m_bRestartDrawing(false),
101 m_eSelMode(ShellMode::Object
), // initially invalid
102 m_pPointNode(nullptr),
103 m_pMarkNode(nullptr),
106 m_pOutliner(nullptr),
107 m_bTextObjectsCollected(false)
110 // reset state in ::InvalidateSpellDialog
112 { m_bInitialCall
= true;
113 m_bBodySpelled
= m_bOtherSpelled
= m_bDrawingsSpelled
= false;
114 m_xStartRange
= nullptr;
115 m_pStartDrawing
= nullptr;
116 m_bRestartDrawing
= false;
117 m_bTextObjectsCollected
= false;
118 m_aTextObjects
.clear();
119 m_bStartedInOther
= false;
120 pOtherCursor
.reset();
124 static void lcl_LeaveDrawText(SwWrtShell
& rSh
)
126 if(rSh
.GetDrawView())
128 rSh
.GetDrawView()->SdrEndTextEdit( true );
129 Point
aPt(LONG_MIN
, LONG_MIN
);
130 // go out of the frame
131 rSh
.SelectObj(aPt
, SW_LEAVE_FRAME
);
133 rSh
.GetView().AttrChangedNotify(nullptr);
137 SwSpellDialogChildWindow::SwSpellDialogChildWindow (
138 vcl::Window
* _pParent
,
140 SfxBindings
* pBindings
,
141 SfxChildWinInfo
* /*pInfo*/)
142 : svx::SpellDialogChildWindow (
143 _pParent
, nId
, pBindings
)
144 , m_bIsGrammarCheckingOn(false)
145 , m_pSpellState(new SpellState
)
147 SvtLinguConfig().GetProperty( UPN_IS_GRAMMAR_INTERACTIVE
) >>= m_bIsGrammarCheckingOn
;
150 SwSpellDialogChildWindow::~SwSpellDialogChildWindow ()
152 SwWrtShell
* pWrtShell
= GetWrtShell_Impl();
153 if(!m_pSpellState
->m_bInitialCall
&& pWrtShell
)
154 pWrtShell
->SpellEnd();
155 m_pSpellState
.reset();
158 SfxChildWinInfo
SwSpellDialogChildWindow::GetInfo() const
160 SfxChildWinInfo aInfo
= svx::SpellDialogChildWindow::GetInfo();
161 aInfo
.bVisible
= false;
165 svx::SpellPortions
SwSpellDialogChildWindow::GetNextWrongSentence(bool bRecheck
)
167 svx::SpellPortions aRet
;
168 SwWrtShell
* pWrtShell
= GetWrtShell_Impl();
171 bool bNoDictionaryAvailable
= pWrtShell
->GetDoc()->IsDictionaryMissing();
175 // first set continuation point for spell/grammar check to the
176 // end of the current sentence
177 SwEditShell::MoveContinuationPosToEndOfCheckedSentence();
180 ShellMode eSelMode
= pWrtShell
->GetView().GetShellMode();
181 bool bDrawText
= ShellMode::DrawText
== eSelMode
;
183 ShellMode::TableText
== eSelMode
||
184 ShellMode::ListText
== eSelMode
||
185 ShellMode::TableListText
== eSelMode
||
186 ShellMode::Text
== eSelMode
;
187 // Writer text outside of the body
188 bool bOtherText
= false;
190 if( m_pSpellState
->m_bInitialCall
)
192 // if no text selection exists the cursor has to be set into the text
193 if(!bDrawText
&& !bNormalText
)
195 MakeTextSelection_Impl(*pWrtShell
, eSelMode
);
196 // the selection type has to be checked again - both text types are possible
197 if(pWrtShell
->GetSelectionType() & SelectionType::DrawObjectEditMode
)
199 bNormalText
= !bDrawText
;
203 // set cursor to the start of the sentence
204 if(!pWrtShell
->HasSelection())
205 pWrtShell
->GoStartSentence();
208 pWrtShell
->ExpandToSentenceBorders();
209 m_pSpellState
->m_bStartedInSelection
= true;
211 // determine if the selection is outside of the body text
212 bOtherText
= !(pWrtShell
->GetFrameType(nullptr,true) & FrameTypeFlags::BODY
);
215 m_pSpellState
->pOtherCursor
.reset( new SwPaM(*pWrtShell
->GetCursor()->GetPoint()) );
216 m_pSpellState
->m_bStartedInOther
= true;
217 pWrtShell
->SpellStart( SwDocPositions::OtherStart
, SwDocPositions::OtherEnd
, SwDocPositions::Curr
);
221 // mark the start position only if not at start of doc
222 if(!pWrtShell
->IsStartOfDoc())
224 // Record the position *before* the current cursor, as
225 // the word at the current cursor can possibly be
226 // replaced by a spellcheck correction which invalidates
227 // an XTextRange at this position.
228 SwDoc
*pDoc
= pWrtShell
->GetDoc();
229 auto pStart
= pWrtShell
->GetCursor()->Start();
230 auto pUnoCursor
= pDoc
->CreateUnoCursor(*pStart
);
231 pUnoCursor
->Left( 1 );
232 pStart
= pUnoCursor
->Start();
233 m_pSpellState
->m_xStartRange
234 = SwXTextRange::CreateXTextRange(*pDoc
, *pStart
, nullptr);
236 pWrtShell
->SpellStart( SwDocPositions::Start
, SwDocPositions::End
, SwDocPositions::Curr
);
241 SdrView
* pSdrView
= pWrtShell
->GetDrawView();
242 m_pSpellState
->m_pStartDrawing
= pSdrView
->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
243 OutlinerView
* pOLV
= pSdrView
->GetTextEditOutlinerView();
244 // start checking at the top of the drawing object
245 pOLV
->SetSelection( ESelection() );
246 m_pSpellState
->m_aStartDrawingSelection
= ESelection();
248 Note: spelling in a selection only, or starting in a mid of a drawing object requires
249 further changes elsewhere. (Especially if it should work in sc and sd as well.)
250 The code below would only be part of the solution.
251 (Keeping it as a comment for the time being)
252 ESelection aCurSel( pOLV->GetSelection() );
253 ESelection aSentenceSel( pOLV->GetEditView().GetEditEngine()->SelectSentence( aCurSel ) );
254 if (!aCurSel.HasRange())
256 aSentenceSel.nEndPara = aSentenceSel.nStartPara;
257 aSentenceSel.nEndPos = aSentenceSel.nStartPos;
259 pOLV->SetSelection( aSentenceSel );
260 m_pSpellState->m_aStartDrawingSelection = aSentenceSel;
264 m_pSpellState
->m_bInitialCall
= false;
268 // spell inside of the current draw text
269 if(!SpellDrawText_Impl(*pWrtShell
, aRet
))
271 if(!FindNextDrawTextError_Impl(*pWrtShell
) || !SpellDrawText_Impl(*pWrtShell
, aRet
))
273 lcl_LeaveDrawText(*pWrtShell
);
274 // now the drawings have been spelled
275 m_pSpellState
->m_bDrawingsSpelled
= true;
276 // the spelling continues at the other content
277 // if there's any that has not been spelled yet
278 if(!m_pSpellState
->m_bOtherSpelled
&& pWrtShell
->HasOtherCnt())
280 pWrtShell
->SpellStart(SwDocPositions::OtherStart
, SwDocPositions::OtherEnd
, SwDocPositions::OtherStart
);
281 if(!pWrtShell
->SpellSentence(aRet
, m_bIsGrammarCheckingOn
))
283 pWrtShell
->SpellEnd();
284 m_pSpellState
->m_bOtherSpelled
= true;
288 m_pSpellState
->m_bOtherSpelled
= true;
289 // if no result has been found try at the body text - completely
290 if(!m_pSpellState
->m_bBodySpelled
&& aRet
.empty())
292 pWrtShell
->SpellStart(SwDocPositions::Start
, SwDocPositions::End
, SwDocPositions::Start
);
293 if(!pWrtShell
->SpellSentence(aRet
, m_bIsGrammarCheckingOn
))
295 m_pSpellState
->m_bBodySpelled
= true;
296 pWrtShell
->SpellEnd();
305 // spell inside of the Writer text
306 if(!pWrtShell
->SpellSentence(aRet
, m_bIsGrammarCheckingOn
))
308 // if there is a selection (within body or header/footer text)
309 // then spell/grammar checking should not move outside of it.
310 if (!m_pSpellState
->m_bStartedInSelection
)
312 // find out which text has been spelled body or other
313 bOtherText
= !(pWrtShell
->GetFrameType(nullptr,true) & FrameTypeFlags::BODY
);
314 if(bOtherText
&& m_pSpellState
->m_bStartedInOther
&& m_pSpellState
->pOtherCursor
)
316 m_pSpellState
->m_bStartedInOther
= false;
317 pWrtShell
->SetSelection(*m_pSpellState
->pOtherCursor
);
318 pWrtShell
->SpellEnd();
319 m_pSpellState
->pOtherCursor
.reset();
320 pWrtShell
->SpellStart(SwDocPositions::OtherStart
, SwDocPositions::Curr
, SwDocPositions::OtherStart
);
321 (void)pWrtShell
->SpellSentence(aRet
, m_bIsGrammarCheckingOn
);
326 pWrtShell
->SpellEnd();
329 m_pSpellState
->m_bOtherSpelled
= true;
330 // has the body been spelled?
331 if(!m_pSpellState
->m_bBodySpelled
)
333 pWrtShell
->SpellStart(SwDocPositions::Start
, SwDocPositions::End
, SwDocPositions::Start
);
334 if(!pWrtShell
->SpellSentence(aRet
, m_bIsGrammarCheckingOn
))
336 m_pSpellState
->m_bBodySpelled
= true;
337 pWrtShell
->SpellEnd();
343 m_pSpellState
->m_bBodySpelled
= true;
344 if(!m_pSpellState
->m_bOtherSpelled
&& pWrtShell
->HasOtherCnt())
346 pWrtShell
->SpellStart(SwDocPositions::OtherStart
, SwDocPositions::OtherEnd
, SwDocPositions::OtherStart
);
347 if(!pWrtShell
->SpellSentence(aRet
, m_bIsGrammarCheckingOn
))
349 pWrtShell
->SpellEnd();
350 m_pSpellState
->m_bOtherSpelled
= true;
354 m_pSpellState
->m_bOtherSpelled
= true;
358 // search for a draw text object that contains error and spell it
360 (m_pSpellState
->m_bDrawingsSpelled
||
361 !FindNextDrawTextError_Impl(*pWrtShell
) || !SpellDrawText_Impl(*pWrtShell
, aRet
)))
363 lcl_LeaveDrawText(*pWrtShell
);
364 m_pSpellState
->m_bDrawingsSpelled
= true;
369 // now only the rest of the body text can be spelled -
370 // if the spelling started inside of the body
371 bool bCloseMessage
= true;
372 if(aRet
.empty() && !m_pSpellState
->m_bStartedInSelection
)
374 OSL_ENSURE(m_pSpellState
->m_bDrawingsSpelled
&&
375 m_pSpellState
->m_bOtherSpelled
&& m_pSpellState
->m_bBodySpelled
,
376 "not all parts of the document are already spelled");
377 if( m_pSpellState
->m_xStartRange
.is() && !bNoDictionaryAvailable
)
379 LockFocusNotification( true );
380 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(GetController()->getDialog(),
381 VclMessageType::Question
, VclButtonsType::YesNo
, SwResId(STR_QUERY_SPELL_CONTINUE
)));
382 sal_uInt16 nRet
= xBox
->run();
385 SwUnoInternalPaM
aPam(*pWrtShell
->GetDoc());
386 if (::sw::XTextRangeToSwPaM(aPam
,
387 m_pSpellState
->m_xStartRange
))
389 pWrtShell
->SetSelection(aPam
);
390 pWrtShell
->SpellStart(SwDocPositions::Start
, SwDocPositions::Curr
, SwDocPositions::Start
);
391 if(!pWrtShell
->SpellSentence(aRet
, m_bIsGrammarCheckingOn
))
392 pWrtShell
->SpellEnd();
394 m_pSpellState
->m_xStartRange
= nullptr;
395 LockFocusNotification( false );
396 // take care that the now valid selection is stored
400 bCloseMessage
= false; // no closing message if a wrap around has been denied
403 if( aRet
.empty() && bCloseMessage
&& !bNoDictionaryAvailable
)
405 LockFocusNotification( true );
406 OUString
sInfo( SwResId( bNoDictionaryAvailable
? STR_DICTIONARY_UNAVAILABLE
: STR_SPELLING_COMPLETED
) );
407 auto xSpellController
= GetController();
409 std::unique_ptr
<weld::MessageDialog
> xBox(
410 Application::CreateMessageDialog( xSpellController
->getDialog(),
411 VclMessageType::Info
,
415 LockFocusNotification( false );
416 // take care that the now valid selection is stored
418 xSpellController
->getDialog()->grab_focus();
424 void SwSpellDialogChildWindow::ApplyChangedSentence(const svx::SpellPortions
& rChanged
, bool bRecheck
)
426 SwWrtShell
* pWrtShell
= GetWrtShell_Impl();
427 OSL_ENSURE(!m_pSpellState
->m_bInitialCall
, "ApplyChangedSentence in initial call or after resume");
428 if(!pWrtShell
|| m_pSpellState
->m_bInitialCall
)
431 ShellMode eSelMode
= pWrtShell
->GetView().GetShellMode();
432 bool bDrawText
= ShellMode::DrawText
== eSelMode
;
434 ShellMode::TableText
== eSelMode
||
435 ShellMode::ListText
== eSelMode
||
436 ShellMode::TableListText
== eSelMode
||
437 ShellMode::Text
== eSelMode
;
439 // evaluate if the same sentence should be rechecked or not.
440 // Sentences that got grammar checked should always be rechecked in order
441 // to detect possible errors that get introduced with the changes
442 bRecheck
|= SwEditShell::HasLastSentenceGotGrammarChecked();
445 pWrtShell
->ApplyChangedSentence(rChanged
, bRecheck
);
448 SdrView
* pDrView
= pWrtShell
->GetDrawView();
449 SdrOutliner
*pOutliner
= pDrView
->GetTextEditOutliner();
450 pOutliner
->ApplyChangedSentence(pDrView
->GetTextEditOutlinerView()->GetEditView(), rChanged
, bRecheck
);
454 void SwSpellDialogChildWindow::AddAutoCorrection(
455 const OUString
& rOld
, const OUString
& rNew
, LanguageType eLanguage
)
457 SvxAutoCorrect
* pACorr
= SvxAutoCorrCfg::Get().GetAutoCorrect();
458 pACorr
->PutText( rOld
, rNew
, eLanguage
);
461 bool SwSpellDialogChildWindow::HasAutoCorrection()
466 bool SwSpellDialogChildWindow::HasGrammarChecking()
468 return SvtLinguConfig().HasGrammarChecker();
471 bool SwSpellDialogChildWindow::IsGrammarChecking()
473 return m_bIsGrammarCheckingOn
;
476 void SwSpellDialogChildWindow::SetGrammarChecking(bool bOn
)
480 m_bIsGrammarCheckingOn
= bOn
;
481 SvtLinguConfig().SetProperty( UPN_IS_GRAMMAR_INTERACTIVE
, aVal
);
482 // set current spell position to the start of the current sentence to
483 // continue with this sentence after grammar checking state has been changed
484 SwWrtShell
* pWrtShell
= GetWrtShell_Impl();
488 ShellMode eSelMode
= pWrtShell
->GetView().GetShellMode();
489 bool bDrawText
= ShellMode::DrawText
== eSelMode
;
491 ShellMode::TableText
== eSelMode
||
492 ShellMode::ListText
== eSelMode
||
493 ShellMode::TableListText
== eSelMode
||
494 ShellMode::Text
== eSelMode
;
496 SwEditShell::PutSpellingToSentenceStart();
499 SdrView
* pSdrView
= pWrtShell
->GetDrawView();
500 SdrOutliner
* pOutliner
= pSdrView
? pSdrView
->GetTextEditOutliner() : nullptr;
501 OSL_ENSURE(pOutliner
, "No Outliner in SwSpellDialogChildWindow::SetGrammarChecking");
504 pOutliner
->PutSpellingToSentenceStart( pSdrView
->GetTextEditOutlinerView()->GetEditView() );
509 void SwSpellDialogChildWindow::GetFocus()
511 if(m_pSpellState
->m_bLockFocus
)
513 bool bInvalidate
= false;
514 SwWrtShell
* pWrtShell
= GetWrtShell_Impl();
515 if(pWrtShell
&& !m_pSpellState
->m_bInitialCall
)
517 ShellMode eSelMode
= pWrtShell
->GetView().GetShellMode();
518 if(eSelMode
!= m_pSpellState
->m_eSelMode
)
520 // prevent initial invalidation
521 if(m_pSpellState
->m_bLostFocus
)
526 switch(m_pSpellState
->m_eSelMode
)
528 case ShellMode::Text
:
529 case ShellMode::ListText
:
530 case ShellMode::TableText
:
531 case ShellMode::TableListText
:
533 SwPaM
* pCursor
= pWrtShell
->GetCursor();
534 if(m_pSpellState
->m_pPointNode
!= &pCursor
->GetPointNode() ||
535 m_pSpellState
->m_pMarkNode
!= &pCursor
->GetMarkNode()||
536 m_pSpellState
->m_nPointPos
!= pCursor
->GetPoint()->GetContentIndex()||
537 m_pSpellState
->m_nMarkPos
!= pCursor
->GetMark()->GetContentIndex())
541 case ShellMode::DrawText
:
543 SdrView
* pSdrView
= pWrtShell
->GetDrawView();
544 SdrOutliner
* pOutliner
= pSdrView
? pSdrView
->GetTextEditOutliner() : nullptr;
545 if(!pOutliner
|| m_pSpellState
->m_pOutliner
!= pOutliner
)
549 OutlinerView
* pOLV
= pSdrView
->GetTextEditOutlinerView();
550 OSL_ENSURE(pOLV
, "no OutlinerView in SwSpellDialogChildWindow::GetFocus()");
551 if(!pOLV
|| m_pSpellState
->m_aESelection
!= pOLV
->GetSelection())
556 default: bInvalidate
= true;
565 InvalidateSpellDialog();
568 void SwSpellDialogChildWindow::LoseFocus()
570 // prevent initial invalidation
571 m_pSpellState
->m_bLostFocus
= true;
572 if(m_pSpellState
->m_bLockFocus
)
574 SwWrtShell
* pWrtShell
= GetWrtShell_Impl();
577 m_pSpellState
->m_eSelMode
= pWrtShell
->GetView().GetShellMode();
578 m_pSpellState
->m_pPointNode
= m_pSpellState
->m_pMarkNode
= nullptr;
579 m_pSpellState
->m_nPointPos
= m_pSpellState
->m_nMarkPos
= 0;
580 m_pSpellState
->m_pOutliner
= nullptr;
582 switch(m_pSpellState
->m_eSelMode
)
584 case ShellMode::Text
:
585 case ShellMode::ListText
:
586 case ShellMode::TableText
:
587 case ShellMode::TableListText
:
589 // store a node pointer and a pam-position to be able to check on next GetFocus();
590 SwPaM
* pCursor
= pWrtShell
->GetCursor();
591 m_pSpellState
->m_pPointNode
= &pCursor
->GetPointNode();
592 m_pSpellState
->m_pMarkNode
= &pCursor
->GetMarkNode();
593 m_pSpellState
->m_nPointPos
= pCursor
->GetPoint()->GetContentIndex();
594 m_pSpellState
->m_nMarkPos
= pCursor
->GetMark()->GetContentIndex();
598 case ShellMode::DrawText
:
600 SdrView
* pSdrView
= pWrtShell
->GetDrawView();
601 SdrOutliner
* pOutliner
= pSdrView
->GetTextEditOutliner();
602 m_pSpellState
->m_pOutliner
= pOutliner
;
603 OutlinerView
* pOLV
= pSdrView
->GetTextEditOutlinerView();
604 OSL_ENSURE(pOutliner
&& pOLV
, "no Outliner/OutlinerView in SwSpellDialogChildWindow::LoseFocus()");
607 m_pSpellState
->m_aESelection
= pOLV
->GetSelection();
611 default:;// prevent warning
615 m_pSpellState
->m_eSelMode
= ShellMode::Object
;
618 void SwSpellDialogChildWindow::InvalidateSpellDialog()
620 SwWrtShell
* pWrtShell
= GetWrtShell_Impl();
621 if(!m_pSpellState
->m_bInitialCall
&& pWrtShell
)
622 pWrtShell
->SpellEnd(nullptr, false);
623 m_pSpellState
->Reset();
624 svx::SpellDialogChildWindow::InvalidateSpellDialog();
627 SwWrtShell
* SwSpellDialogChildWindow::GetWrtShell_Impl()
629 SfxDispatcher
* pDispatch
= GetBindings().GetDispatcher();
630 SwView
* pView
= nullptr;
633 sal_uInt16 nShellIdx
= 0;
635 while(nullptr != (pShell
= pDispatch
->GetShell(nShellIdx
++)))
636 if(auto pSwView
= dynamic_cast< SwView
*>( pShell
))
642 return pView
? pView
->GetWrtShellPtr(): nullptr;
645 // set the cursor into the body text - necessary if any object is selected
646 // on start of the spelling dialog
647 void SwSpellDialogChildWindow::MakeTextSelection_Impl(SwWrtShell
& rShell
, ShellMode eSelMode
)
649 SwView
& rView
= rShell
.GetView();
652 case ShellMode::Text
:
653 case ShellMode::ListText
:
654 case ShellMode::TableText
:
655 case ShellMode::TableListText
:
656 case ShellMode::DrawText
:
657 OSL_FAIL("text already active in SwSpellDialogChildWindow::MakeTextSelection_Impl()");
660 case ShellMode::Frame
:
662 rShell
.UnSelectFrame();
663 rShell
.LeaveSelFrameMode();
664 rView
.AttrChangedNotify(nullptr);
668 case ShellMode::Draw
:
669 case ShellMode::DrawForm
:
670 case ShellMode::Bezier
:
671 if(FindNextDrawTextError_Impl(rShell
))
673 rView
.AttrChangedNotify(nullptr);
676 [[fallthrough
]]; // to deselect the object
677 case ShellMode::Graphic
:
678 case ShellMode::Object
:
680 if ( rShell
.IsDrawCreate() )
682 rView
.GetDrawFuncPtr()->BreakCreate();
683 rView
.AttrChangedNotify(nullptr);
685 else if ( rShell
.HasSelection() || rView
.IsDrawMode() )
687 SdrView
*pSdrView
= rShell
.GetDrawView();
688 if(pSdrView
&& pSdrView
->AreObjectsMarked() &&
689 pSdrView
->GetHdlList().GetFocusHdl())
691 const_cast<SdrHdlList
&>(pSdrView
->GetHdlList()).ResetFocusHdl();
695 rView
.LeaveDrawCreate();
696 Point
aPt(LONG_MIN
, LONG_MIN
);
697 // go out of the frame
698 rShell
.SelectObj(aPt
, SW_LEAVE_FRAME
);
699 SfxBindings
& rBind
= rView
.GetViewFrame().GetBindings();
700 rBind
.Invalidate( SID_ATTR_SIZE
);
701 rShell
.EnterStdMode();
702 rView
.AttrChangedNotify(nullptr);
707 default:; // prevent warning
711 // select the next draw text object that has a spelling error
712 bool SwSpellDialogChildWindow::FindNextDrawTextError_Impl(SwWrtShell
& rSh
)
714 bool bNextDoc
= false;
715 SdrView
* pDrView
= rSh
.GetDrawView();
718 SwView
& rView
= rSh
.GetView();
719 SwDoc
* pDoc
= rView
.GetDocShell()->GetDoc();
720 const SdrMarkList
& rMarkList
= pDrView
->GetMarkedObjectList();
721 // start at the current draw object - if there is any selected
722 SdrTextObj
* pCurrentTextObj
= nullptr;
723 if ( rMarkList
.GetMarkCount() == 1 )
725 SdrObject
* pObj
= rMarkList
.GetMark(0)->GetMarkedSdrObj();
726 if( auto pSdrTextObj
= DynCastSdrTextObj( pObj
) )
727 pCurrentTextObj
= pSdrTextObj
;
729 // at first fill the list of drawing objects
730 if(!m_pSpellState
->m_bTextObjectsCollected
)
732 m_pSpellState
->m_bTextObjectsCollected
= true;
733 SwDrawContact::GetTextObjectsFromFormat(m_pSpellState
->m_aTextObjects
, *pDoc
);
736 m_pSpellState
->m_aTextObjects
.remove(pCurrentTextObj
);
737 m_pSpellState
->m_aTextObjects
.push_back(pCurrentTextObj
);
740 if(!m_pSpellState
->m_aTextObjects
.empty())
742 Reference
< XSpellChecker1
> xSpell( GetSpellChecker() );
743 while(!bNextDoc
&& !m_pSpellState
->m_aTextObjects
.empty())
745 std::list
<SdrTextObj
*>::iterator aStart
= m_pSpellState
->m_aTextObjects
.begin();
746 SdrTextObj
* pTextObj
= *aStart
;
747 if(m_pSpellState
->m_pStartDrawing
== pTextObj
)
748 m_pSpellState
->m_bRestartDrawing
= true;
749 m_pSpellState
->m_aTextObjects
.erase(aStart
);
750 OutlinerParaObject
* pParaObj
= pTextObj
->GetOutlinerParaObject();
753 bool bHasSpellError
= false;
755 SdrOutliner
aTmpOutliner(pDoc
->getIDocumentDrawModelAccess().GetDrawModel()->
756 GetDrawOutliner().GetEmptyItemSet().GetPool(),
757 OutlinerMode::TextObject
);
758 aTmpOutliner
.SetRefDevice( pDoc
->getIDocumentDeviceAccess().getPrinter( false ) );
759 MapMode
aMapMode (MapUnit::MapTwip
);
760 aTmpOutliner
.SetRefMapMode(aMapMode
);
761 aTmpOutliner
.SetPaperSize( pTextObj
->GetLogicRect().GetSize() );
762 aTmpOutliner
.SetSpeller( xSpell
);
764 OutlinerView
aOutlView( &aTmpOutliner
, &(rView
.GetEditWin()) );
765 aOutlView
.GetOutliner()->SetRefDevice( rSh
.getIDocumentDeviceAccess().getPrinter( false ) );
766 aTmpOutliner
.InsertView( &aOutlView
);
768 tools::Rectangle
aRect( Point(), aSize
);
769 aOutlView
.SetOutputArea( aRect
);
770 aTmpOutliner
.SetText( *pParaObj
);
771 aTmpOutliner
.ClearModifyFlag();
772 bHasSpellError
= EESpellState::Ok
!= aTmpOutliner
.HasSpellErrors();
773 aTmpOutliner
.RemoveView( &aOutlView
);
777 // now the current one has to be deselected
779 pDrView
->SdrEndTextEdit( true );
780 // and the found one should be activated
781 rSh
.MakeVisible(SwRect(pTextObj
->GetLogicRect()));
783 rSh
.SelectObj( aTmp
, 0, pTextObj
);
784 SdrPageView
* pPV
= pDrView
->GetSdrPageView();
785 rView
.BeginTextEdit( pTextObj
, pPV
, &rView
.GetEditWin(), false, true );
786 rView
.AttrChangedNotify(nullptr);
795 bool SwSpellDialogChildWindow::SpellDrawText_Impl(SwWrtShell
& rSh
, svx::SpellPortions
& rPortions
)
798 SdrView
* pSdrView
= rSh
.GetDrawView();
799 SdrOutliner
* pOutliner
= pSdrView
? pSdrView
->GetTextEditOutliner() : nullptr;
800 OSL_ENSURE(pOutliner
, "No Outliner in SwSpellDialogChildWindow::SpellDrawText_Impl");
803 bRet
= pOutliner
->SpellSentence(pSdrView
->GetTextEditOutlinerView()->GetEditView(), rPortions
);
804 // find out if the current selection is in the first spelled drawing object
805 // and behind the initial selection
806 if(bRet
&& m_pSpellState
->m_bRestartDrawing
)
808 OutlinerView
* pOLV
= pSdrView
->GetTextEditOutlinerView();
809 ESelection aCurrentSelection
= pOLV
->GetSelection();
810 if(m_pSpellState
->m_aStartDrawingSelection
.nEndPara
< aCurrentSelection
.nEndPara
||
811 (m_pSpellState
->m_aStartDrawingSelection
.nEndPara
== aCurrentSelection
.nEndPara
&&
812 m_pSpellState
->m_aStartDrawingSelection
.nEndPos
< aCurrentSelection
.nEndPos
))
822 void SwSpellDialogChildWindow::LockFocusNotification(bool bLock
)
824 OSL_ENSURE(m_pSpellState
->m_bLockFocus
!= bLock
, "invalid locking - no change of state");
825 m_pSpellState
->m_bLockFocus
= bLock
;
828 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */