LibreOffice Module sw (master)  1
SwSpellDialogChildWindow.cxx
Go to the documentation of this file.
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 <memory>
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>
29 #include <wrtsh.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>
36 #include <doc.hxx>
39 #include <docsh.hxx>
40 #include <drawdoc.hxx>
41 #include <dcontact.hxx>
42 #include <edtwin.hxx>
43 #include <pam.hxx>
44 #include <drawbase.hxx>
45 #include <unotextrange.hxx>
46 #include <strings.hrc>
47 #include <cmdid.h>
48 
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;
54 
56 
57 struct SpellState
58 {
60  bool m_bLockFocus; // lock the focus notification while a modal dialog is active
62 
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
75 
76  // lose/get focus information to decide if spelling can be continued
80  sal_Int32 m_nPointPos;
81  sal_Int32 m_nMarkPos;
84 
85  // iterating over draw text objects
86  std::list<SdrTextObj*> m_aTextObjects;
88 
90  m_bInitialCall(true),
91  m_bLockFocus(false),
92  m_bLostFocus(false),
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),
100 
101  m_eSelMode(ShellMode::Object), // initially invalid
102  m_pPointNode(nullptr),
103  m_pMarkNode(nullptr),
104  m_nPointPos(0),
105  m_nMarkPos(0),
106  m_pOutliner(nullptr),
107  m_bTextObjectsCollected(false)
108  {}
109 
110  // reset state in ::InvalidateSpellDialog
111  void Reset()
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();
121  }
122 };
123 
124 static void lcl_LeaveDrawText(SwWrtShell& rSh)
125 {
126  if(rSh.GetDrawView())
127  {
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);
132  rSh.EnterStdMode();
133  rSh.GetView().AttrChangedNotify(nullptr);
134  }
135 }
136 
138  vcl::Window* _pParent,
139  sal_uInt16 nId,
140  SfxBindings* pBindings,
141  SfxChildWinInfo* /*pInfo*/)
142  : svx::SpellDialogChildWindow (
143  _pParent, nId, pBindings)
144  , m_bIsGrammarCheckingOn(false)
145  , m_pSpellState(new SpellState)
146 {
148 }
149 
151 {
152  SwWrtShell* pWrtShell = GetWrtShell_Impl();
153  if(!m_pSpellState->m_bInitialCall && pWrtShell)
154  pWrtShell->SpellEnd();
155  m_pSpellState.reset();
156 }
157 
158 SfxChildWinInfo SwSpellDialogChildWindow::GetInfo() const
159 {
160  SfxChildWinInfo aInfo = svx::SpellDialogChildWindow::GetInfo();
161  aInfo.bVisible = false;
162  return aInfo;
163 }
164 
166 {
167  svx::SpellPortions aRet;
168  SwWrtShell* pWrtShell = GetWrtShell_Impl();
169  if(pWrtShell)
170  {
171  bool bNoDictionaryAvailable = pWrtShell->GetDoc()->IsDictionaryMissing();
172 
173  if (!bRecheck)
174  {
175  // first set continuation point for spell/grammar check to the
176  // end of the current sentence
178  }
179 
180  ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
181  bool bDrawText = ShellMode::DrawText == eSelMode;
182  bool bNormalText =
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;
189 
190  if( m_pSpellState->m_bInitialCall )
191  {
192  // if no text selection exists the cursor has to be set into the text
193  if(!bDrawText && !bNormalText)
194  {
195  MakeTextSelection_Impl(*pWrtShell, eSelMode);
196  // the selection type has to be checked again - both text types are possible
198  bDrawText = true;
199  bNormalText = !bDrawText;
200  }
201  if(bNormalText)
202  {
203  // set cursor to the start of the sentence
204  if(!pWrtShell->HasSelection())
205  pWrtShell->GoStartSentence();
206  else
207  {
208  pWrtShell->ExpandToSentenceBorders();
209  m_pSpellState->m_bStartedInSelection = true;
210  }
211  // determine if the selection is outside of the body text
212  bOtherText = !(pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY);
213  if(bOtherText)
214  {
215  m_pSpellState->pOtherCursor.reset( new SwPaM(*pWrtShell->GetCursor()->GetPoint()) );
216  m_pSpellState->m_bStartedInOther = true;
218  }
219  else
220  {
221  // mark the start position only if not at start of doc
222  if(!pWrtShell->IsStartOfDoc())
223  {
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);
235  }
237  }
238  }
239  else
240  {
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();
247 /*
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())
255  {
256  aSentenceSel.nEndPara = aSentenceSel.nStartPara;
257  aSentenceSel.nEndPos = aSentenceSel.nStartPos;
258  }
259  pOLV->SetSelection( aSentenceSel );
260  m_pSpellState->m_aStartDrawingSelection = aSentenceSel;
261 */
262  }
263 
264  m_pSpellState->m_bInitialCall = false;
265  }
266  if( bDrawText )
267  {
268  // spell inside of the current draw text
269  if(!SpellDrawText_Impl(*pWrtShell, aRet))
270  {
271  if(!FindNextDrawTextError_Impl(*pWrtShell) || !SpellDrawText_Impl(*pWrtShell, aRet))
272  {
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())
279  {
281  if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
282  {
283  pWrtShell->SpellEnd();
284  m_pSpellState->m_bOtherSpelled = true;
285  }
286  }
287  else
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())
291  {
293  if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
294  {
295  m_pSpellState->m_bBodySpelled = true;
296  pWrtShell->SpellEnd();
297  }
298  }
299 
300  }
301  }
302  }
303  else
304  {
305  // spell inside of the Writer text
306  if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
307  {
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)
311  {
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)
315  {
316  m_pSpellState->m_bStartedInOther = false;
317  pWrtShell->SetSelection(*m_pSpellState->pOtherCursor);
318  pWrtShell->SpellEnd();
319  m_pSpellState->pOtherCursor.reset();
321  (void)pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn);
322  }
323  if(aRet.empty())
324  {
325  // end spelling
326  pWrtShell->SpellEnd();
327  if(bOtherText)
328  {
329  m_pSpellState->m_bOtherSpelled = true;
330  // has the body been spelled?
331  if(!m_pSpellState->m_bBodySpelled)
332  {
334  if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
335  {
336  m_pSpellState->m_bBodySpelled = true;
337  pWrtShell->SpellEnd();
338  }
339  }
340  }
341  else
342  {
343  m_pSpellState->m_bBodySpelled = true;
344  if(!m_pSpellState->m_bOtherSpelled && pWrtShell->HasOtherCnt())
345  {
347  if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
348  {
349  pWrtShell->SpellEnd();
350  m_pSpellState->m_bOtherSpelled = true;
351  }
352  }
353  else
354  m_pSpellState->m_bOtherSpelled = true;
355  }
356  }
357 
358  // search for a draw text object that contains error and spell it
359  if(aRet.empty() &&
360  (m_pSpellState->m_bDrawingsSpelled ||
361  !FindNextDrawTextError_Impl(*pWrtShell) || !SpellDrawText_Impl(*pWrtShell, aRet)))
362  {
363  lcl_LeaveDrawText(*pWrtShell);
364  m_pSpellState->m_bDrawingsSpelled = true;
365  }
366  }
367  }
368  }
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)
373  {
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 )
378  {
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();
383  if (RET_YES == nRet)
384  {
385  SwUnoInternalPaM aPam(*pWrtShell->GetDoc());
386  if (::sw::XTextRangeToSwPaM(aPam,
387  m_pSpellState->m_xStartRange))
388  {
389  pWrtShell->SetSelection(aPam);
391  if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
392  pWrtShell->SpellEnd();
393  }
394  m_pSpellState->m_xStartRange = nullptr;
395  LockFocusNotification( false );
396  // take care that the now valid selection is stored
397  LoseFocus();
398  }
399  else
400  bCloseMessage = false; // no closing message if a wrap around has been denied
401  }
402  }
403  if( aRet.empty() && bCloseMessage && !bNoDictionaryAvailable )
404  {
405  LockFocusNotification( true );
406  OUString sInfo( SwResId( bNoDictionaryAvailable ? STR_DICTIONARY_UNAVAILABLE : STR_SPELLING_COMPLETED ) );
407  auto xSpellController = GetController();
408  // #i84610#
409  std::unique_ptr<weld::MessageDialog> xBox(
410  Application::CreateMessageDialog( xSpellController->getDialog(),
411  VclMessageType::Info,
412  VclButtonsType::Ok,
413  sInfo ) );
414  xBox->run();
415  LockFocusNotification( false );
416  // take care that the now valid selection is stored
417  LoseFocus();
418  xSpellController->getDialog()->grab_focus();
419  }
420  }
421  return aRet;
422 }
423 
425 {
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)
429  return;
430 
431  ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
432  bool bDrawText = ShellMode::DrawText == eSelMode;
433  bool bNormalText =
434  ShellMode::TableText == eSelMode ||
435  ShellMode::ListText == eSelMode ||
436  ShellMode::TableListText == eSelMode ||
437  ShellMode::Text == eSelMode;
438 
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
443 
444  if(bNormalText)
445  pWrtShell->ApplyChangedSentence(rChanged, bRecheck);
446  else if(bDrawText )
447  {
448  SdrView* pDrView = pWrtShell->GetDrawView();
449  SdrOutliner *pOutliner = pDrView->GetTextEditOutliner();
450  pOutliner->ApplyChangedSentence(pDrView->GetTextEditOutlinerView()->GetEditView(), rChanged, bRecheck);
451  }
452 }
453 
455  const OUString& rOld, const OUString& rNew, LanguageType eLanguage)
456 {
458  pACorr->PutText( rOld, rNew, eLanguage );
459 }
460 
462 {
463  return true;
464 }
465 
467 {
469 }
470 
472 {
473  return m_bIsGrammarCheckingOn;
474 }
475 
477 {
478  uno::Any aVal;
479  aVal <<= bOn;
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();
485  if(!pWrtShell)
486  return;
487 
488  ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
489  bool bDrawText = ShellMode::DrawText == eSelMode;
490  bool bNormalText =
491  ShellMode::TableText == eSelMode ||
492  ShellMode::ListText == eSelMode ||
493  ShellMode::TableListText == eSelMode ||
494  ShellMode::Text == eSelMode;
495  if( bNormalText )
497  else if( bDrawText )
498  {
499  SdrView* pSdrView = pWrtShell->GetDrawView();
500  SdrOutliner* pOutliner = pSdrView ? pSdrView->GetTextEditOutliner() : nullptr;
501  OSL_ENSURE(pOutliner, "No Outliner in SwSpellDialogChildWindow::SetGrammarChecking");
502  if(pOutliner)
503  {
504  pOutliner->PutSpellingToSentenceStart( pSdrView->GetTextEditOutlinerView()->GetEditView() );
505  }
506  }
507 }
508 
510 {
511  if(m_pSpellState->m_bLockFocus)
512  return;
513  bool bInvalidate = false;
514  SwWrtShell* pWrtShell = GetWrtShell_Impl();
515  if(pWrtShell && !m_pSpellState->m_bInitialCall)
516  {
517  ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
518  if(eSelMode != m_pSpellState->m_eSelMode)
519  {
520  // prevent initial invalidation
521  if(m_pSpellState->m_bLostFocus)
522  bInvalidate = true;
523  }
524  else
525  {
526  switch(m_pSpellState->m_eSelMode)
527  {
528  case ShellMode::Text:
529  case ShellMode::ListText:
532  {
533  SwPaM* pCursor = pWrtShell->GetCursor();
534  if(m_pSpellState->m_pPointNode != &pCursor->GetNode() ||
535  m_pSpellState->m_pMarkNode != &pCursor->GetNode(false)||
536  m_pSpellState->m_nPointPos != pCursor->GetPoint()->nContent.GetIndex()||
537  m_pSpellState->m_nMarkPos != pCursor->GetMark()->nContent.GetIndex())
538  bInvalidate = true;
539  }
540  break;
541  case ShellMode::DrawText:
542  {
543  SdrView* pSdrView = pWrtShell->GetDrawView();
544  SdrOutliner* pOutliner = pSdrView ? pSdrView->GetTextEditOutliner() : nullptr;
545  if(!pOutliner || m_pSpellState->m_pOutliner != pOutliner)
546  bInvalidate = true;
547  else
548  {
549  OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
550  OSL_ENSURE(pOLV, "no OutlinerView in SwSpellDialogChildWindow::GetFocus()");
551  if(!pOLV || m_pSpellState->m_aESelection != pOLV->GetSelection())
552  bInvalidate = true;
553  }
554  }
555  break;
556  default: bInvalidate = true;
557  }
558  }
559  }
560  else
561  {
562  bInvalidate = true;
563  }
564  if(bInvalidate)
566 }
567 
569 {
570  // prevent initial invalidation
571  m_pSpellState->m_bLostFocus = true;
572  if(m_pSpellState->m_bLockFocus)
573  return;
574  SwWrtShell* pWrtShell = GetWrtShell_Impl();
575  if(pWrtShell)
576  {
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;
581 
582  switch(m_pSpellState->m_eSelMode)
583  {
584  case ShellMode::Text:
585  case ShellMode::ListText:
588  {
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->GetNode();
592  m_pSpellState->m_pMarkNode = &pCursor->GetNode(false);
593  m_pSpellState->m_nPointPos = pCursor->GetPoint()->nContent.GetIndex();
594  m_pSpellState->m_nMarkPos = pCursor->GetMark()->nContent.GetIndex();
595 
596  }
597  break;
598  case ShellMode::DrawText:
599  {
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()");
605  if(pOLV)
606  {
607  m_pSpellState->m_aESelection = pOLV->GetSelection();
608  }
609  }
610  break;
611  default:;// prevent warning
612  }
613  }
614  else
615  m_pSpellState->m_eSelMode = ShellMode::Object;
616 }
617 
619 {
620  SwWrtShell* pWrtShell = GetWrtShell_Impl();
621  if(!m_pSpellState->m_bInitialCall && pWrtShell)
622  pWrtShell->SpellEnd(nullptr, false);
623  m_pSpellState->Reset();
625 }
626 
628 {
629  SfxDispatcher* pDispatch = GetBindings().GetDispatcher();
630  SwView* pView = nullptr;
631  if(pDispatch)
632  {
633  sal_uInt16 nShellIdx = 0;
634  SfxShell* pShell;
635  while(nullptr != (pShell = pDispatch->GetShell(nShellIdx++)))
636  if(auto pSwView = dynamic_cast< SwView *>( pShell ))
637  {
638  pView = pSwView;
639  break;
640  }
641  }
642  return pView ? pView->GetWrtShellPtr(): nullptr;
643 }
644 
645 // set the cursor into the body text - necessary if any object is selected
646 // on start of the spelling dialog
648 {
649  SwView& rView = rShell.GetView();
650  switch(eSelMode)
651  {
652  case ShellMode::Text:
653  case ShellMode::ListText:
656  case ShellMode::DrawText:
657  OSL_FAIL("text already active in SwSpellDialogChildWindow::MakeTextSelection_Impl()");
658  break;
659 
660  case ShellMode::Frame:
661  {
662  rShell.UnSelectFrame();
663  rShell.LeaveSelFrameMode();
664  rView.AttrChangedNotify(nullptr);
665  }
666  break;
667 
668  case ShellMode::Draw:
669  case ShellMode::DrawForm:
670  case ShellMode::Bezier:
671  if(FindNextDrawTextError_Impl(rShell))
672  {
673  rView.AttrChangedNotify(nullptr);
674  break;
675  }
676  [[fallthrough]]; // to deselect the object
677  case ShellMode::Graphic:
678  case ShellMode::Object:
679  {
680  if ( rShell.IsDrawCreate() )
681  {
682  rView.GetDrawFuncPtr()->BreakCreate();
683  rView.AttrChangedNotify(nullptr);
684  }
685  else if ( rShell.HasSelection() || rView.IsDrawMode() )
686  {
687  SdrView *pSdrView = rShell.GetDrawView();
688  if(pSdrView && pSdrView->AreObjectsMarked() &&
689  pSdrView->GetHdlList().GetFocusHdl())
690  {
691  const_cast<SdrHdlList&>(pSdrView->GetHdlList()).ResetFocusHdl();
692  }
693  else
694  {
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);
703  }
704  }
705  }
706  break;
707  default:; // prevent warning
708  }
709 }
710 
711 // select the next draw text object that has a spelling error
713 {
714  bool bNextDoc = false;
715  SdrView* pDrView = rSh.GetDrawView();
716  if(!pDrView)
717  return bNextDoc;
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 )
724  {
725  SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
726  if( auto pSdrTextObj = dynamic_cast<SdrTextObj *>( pObj ) )
727  pCurrentTextObj = pSdrTextObj;
728  }
729  // at first fill the list of drawing objects
730  if(!m_pSpellState->m_bTextObjectsCollected )
731  {
732  m_pSpellState->m_bTextObjectsCollected = true;
734  if(pCurrentTextObj)
735  {
736  m_pSpellState->m_aTextObjects.remove(pCurrentTextObj);
737  m_pSpellState->m_aTextObjects.push_back(pCurrentTextObj);
738  }
739  }
740  if(!m_pSpellState->m_aTextObjects.empty())
741  {
742  Reference< XSpellChecker1 > xSpell( GetSpellChecker() );
743  while(!bNextDoc && !m_pSpellState->m_aTextObjects.empty())
744  {
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();
751  if ( pParaObj )
752  {
753  bool bHasSpellError = false;
754  {
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 );
763 
764  OutlinerView aOutlView( &aTmpOutliner, &(rView.GetEditWin()) );
765  aOutlView.GetOutliner()->SetRefDevice( rSh.getIDocumentDeviceAccess().getPrinter( false ) );
766  aTmpOutliner.InsertView( &aOutlView );
767  Size aSize(1,1);
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 );
774  }
775  if(bHasSpellError)
776  {
777  // now the current one has to be deselected
778  if(pCurrentTextObj)
779  pDrView->SdrEndTextEdit( true );
780  // and the found one should be activated
781  rSh.MakeVisible(SwRect(pTextObj->GetLogicRect()));
782  Point aTmp( 0,0 );
783  rSh.SelectObj( aTmp, 0, pTextObj );
784  SdrPageView* pPV = pDrView->GetSdrPageView();
785  rView.BeginTextEdit( pTextObj, pPV, &rView.GetEditWin(), false, true );
786  rView.AttrChangedNotify(nullptr);
787  bNextDoc = true;
788  }
789  }
790  }
791  }
792  return bNextDoc;
793 }
794 
796 {
797  bool bRet = false;
798  SdrView* pSdrView = rSh.GetDrawView();
799  SdrOutliner* pOutliner = pSdrView ? pSdrView->GetTextEditOutliner() : nullptr;
800  OSL_ENSURE(pOutliner, "No Outliner in SwSpellDialogChildWindow::SpellDrawText_Impl");
801  if(pOutliner)
802  {
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)
807  {
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))
813  {
814  bRet = false;
815  rPortions.clear();
816  }
817  }
818  }
819  return bRet;
820 }
821 
823 {
824  OSL_ENSURE(m_pSpellState->m_bLockFocus != bLock, "invalid locking - no change of state");
825  m_pSpellState->m_bLockFocus = bLock;
826 }
827 
828 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SfxViewFrame * GetViewFrame() const
std::shared_ptr< SwUnoCursor > CreateUnoCursor(const SwPosition &rPos, bool bTableCursor=false)
Definition: doc.cxx:1775
SwNode & GetNode(bool bPoint=true) const
Definition: pam.hxx:223
void ExpandToSentenceBorders()
Definition: crstrvl1.cxx:88
size_t GetMarkCount() const
static SvxAutoCorrCfg & Get()
virtual SdrEndTextEditKind SdrEndTextEdit(bool bDontDeleteReally=false)
bool IsDrawMode() const
Definition: view.hxx:539
SdrView * GetDrawView()
Definition: vnew.cxx:373
const SwNode * m_pMarkNode
SwPaM * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:195
bool FindNextDrawTextError_Impl(SwWrtShell &rSh)
bool BeginTextEdit(SdrObject *pObj, SdrPageView *pPV=nullptr, vcl::Window *pWin=nullptr, bool bIsNewObj=false, bool bSetSelectionToStart=false)
Definition: viewdraw.cxx:507
IDocumentDeviceAccess const & getIDocumentDeviceAccess() const
Definition: doc.cxx:238
bool AreObjectsMarked() const
bool IsStartOfDoc() const
Definition: crsrsh.cxx:2750
static bool HasLastSentenceGotGrammarChecked()
Check SwSpellIter data to see if the last sentence got grammar checked.
Definition: edlingu.cxx:598
const SwPosition * GetMark() const
Definition: pam.hxx:209
bool SpellSentence(svx::SpellPortions &rToFill, bool bIsGrammarCheck)
Spells on a sentence basis - the SpellPortions are needed.
Definition: edlingu.cxx:1044
Definition: doc.hxx:188
void EnterStdMode()
Definition: select.cxx:551
SwEditWin & GetEditWin()
Definition: view.hxx:416
SdrMark * GetMark(size_t nNum) const
const SdrObject * m_pStartDrawing
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
Reference< XTextRange > m_xStartRange
void ApplyChangedSentence(const svx::SpellPortions &rNewPortions, bool bRecheck)
Applies a changed sentence.
Definition: edlingu.cxx:1083
void Invalidate(sal_uInt16 nId)
static void GetTextObjectsFromFormat(std::list< SdrTextObj * > &, SwDoc &)
get data collection of anchored objects, handled by with contact
Definition: dcontact.cxx:751
IDocumentDrawModelAccess const & getIDocumentDrawModelAccess() const
Definition: doc.cxx:155
bool GoStartSentence()
Definition: crstrvl1.cxx:78
Used by the UI to modify the document model.
Definition: wrtsh.hxx:93
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:165
void BreakCreate()
Definition: drawbase.cxx:464
std::unique_ptr< SpellState > m_pSpellState
const SwView & GetView() const
Definition: wrtsh.hxx:431
RET_YES
SfxShell * GetShell(sal_uInt16 nIdx) const
SwIndex nContent
Definition: pam.hxx:38
void MakeTextSelection_Impl(SwWrtShell &rSh, ShellMode eSelMode)
const SdrOutliner * m_pOutliner
virtual void LoseFocus() override
SwDoc * GetDoc() const
Definition: viewsh.hxx:281
bool SpellDrawText_Impl(SwWrtShell &rSh, svx::SpellPortions &rPortions)
sal_Int32 nEndPos
ShellMode
Definition: view.hxx:85
EditView & GetEditView() const
virtual ~SwSpellDialogChildWindow() override
void MakeVisible(const SwRect &)
Definition: viewsh.cxx:577
virtual bool HasGrammarChecking() override
#define UPN_IS_GRAMMAR_INTERACTIVE
virtual void GetFocus() override
SdrObject * GetMarkedSdrObj() const
SwDoc * GetDoc()
returns Doc. But be careful!
Definition: docsh.hxx:203
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
const IDocumentDeviceAccess & getIDocumentDeviceAccess() const
Provides access to the document device interface.
Definition: viewsh.cxx:2670
bool HasOtherCnt() const
Are there frames, footnotes, etc.
Definition: edws.cxx:144
sal_Int32 nEndPara
const SdrOutliner * GetTextEditOutliner() const
bool HasSelection() const
Definition: wrtsh.hxx:144
SfxBindings & GetBindings() const
std::unique_ptr< SwPaM > pOtherCursor
ESelection m_aStartDrawingSelection
void SpellEnd(SwConversionArgs const *pConvArgs=nullptr, bool bRestoreSelection=true)
Restore selections.
Definition: edlingu.cxx:671
SwSpellDialogChildWindow(vcl::Window *pParent, sal_uInt16 nId, SfxBindings *pBindings, SfxChildWinInfo *pInfo)
bool HasGrammarChecker() const
const SwPosition * GetPoint() const
Definition: pam.hxx:207
virtual void ApplyChangedSentence(const svx::SpellPortions &rChanged, bool bRecheck) override
SvxAutoCorrect * GetAutoCorrect()
SfxBindings & GetBindings()
const SdrMarkList & GetMarkedObjectList() const
virtual const SwDrawModel * GetDrawModel() const =0
Draw Model and id accessors.
virtual svx::SpellPortions GetNextWrongSentence(bool bRecheck) override
void SetSelection(const SwPaM &rCursor)
Definition: crsrsh.cxx:3538
SFX_IMPL_CHILDWINDOW_WITHID(SearchResultsDlgWrapper, SID_SEARCH_RESULTS_DIALOG)
const OutlinerView * GetTextEditOutlinerView() const
Outliner * GetOutliner() const
virtual bool HasAutoCorrection() override
void LeaveDrawCreate()
Definition: view.hxx:538
SwDrawBase * GetDrawFuncPtr() const
Definition: view.hxx:526
virtual void SetGrammarChecking(bool bOn) override
virtual SfxPrinter * getPrinter(bool bCreate) const =0
Return the printer set at the document.
const SwPosition * Start() const
Definition: pam.hxx:212
SwDocShell * GetDocShell()
Definition: view.cxx:1122
bool XTextRangeToSwPaM(SwUnoInternalPaM &rToFill, const uno::Reference< text::XTextRange > &xTextRange,::sw::TextRangeMode const eMode)
Definition: unoobj2.cxx:1107
static void MoveContinuationPosToEndOfCheckedSentence()
Moves the continuation position to the end of the currently checked sentence.
Definition: edlingu.cxx:1073
ESelection GetSelection() const
bool IsDictionaryMissing() const
Returns true if no dictionary can be found for any content.
Definition: doc.hxx:1661
SdrHdl * GetFocusHdl() const
uno::Reference< linguistic2::XSpellChecker1 > GetSpellChecker()
Definition: swtypes.cxx:52
const SwNode * m_pPointNode
constexpr Size GetSize() const
void SetSelection(const ESelection &)
SwWrtShell * GetWrtShellPtr() const
Definition: view.hxx:414
bool PutText(const OUString &rShort, const OUString &rLong, LanguageType eLang)
#define FN_SPELL_GRAMMAR_DIALOG
Definition: cmdid.h:602
virtual OutlinerParaObject * GetOutlinerParaObject() const override
sal_Int32 GetIndex() const
Definition: index.hxx:91
void SpellStart(SwDocPositions eStart, SwDocPositions eEnd, SwDocPositions eCurr, SwConversionArgs *pConvArgs=nullptr)
Functions used for spell checking and text conversion.
Definition: edlingu.cxx:634
bool SetProperty(const OUString &rPropertyName, const css::uno::Any &rValue)
void SetRefDevice(OutputDevice *pRefDev)
void UnSelectFrame()
Definition: select.cxx:323
void SetOutputArea(const tools::Rectangle &rRect)
bool SelectObj(const Point &rSelPt, sal_uInt8 nFlag=0, SdrObject *pObj=nullptr)
If an object has been given, exactly this object is selected (instead of searching over position)...
Definition: feshview.cxx:177
SdrPageView * GetSdrPageView() const
void LeaveSelFrameMode()
Definition: select.cxx:720
static void lcl_LeaveDrawText(SwWrtShell &rSh)
SfxDispatcher * GetDispatcher() const
static void PutSpellingToSentenceStart()
Make SpellIter start with the current sentence when called next time.
Definition: edlingu.cxx:1059
virtual bool IsGrammarChecking() override
css::uno::Any GetProperty(const OUString &rPropertyName) const
const SdrHdlList & GetHdlList() const
#define SW_LEAVE_FRAME
Definition: fesh.hxx:167
std::vector< SpellPortion > SpellPortions
static css::uno::Reference< css::text::XTextRange > CreateXTextRange(SwDoc &rDoc, const SwPosition &rPos, const SwPosition *const pMark)
Definition: unoobj2.cxx:1225
SelectionType GetSelectionType() const
Definition: wrtsh1.cxx:1432
bool IsDrawCreate() const
Definition: feshview.cxx:2218
ShellMode GetShellMode() const
Definition: view0.cxx:106
FrameTypeFlags GetFrameType(const Point *pPt, bool bStopAtFly) const
For return values see above FrameType.
Definition: fews.cxx:237
std::list< SdrTextObj * > m_aTextObjects
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, bool bMobile=false)
Definition: view.hxx:144
virtual void AddAutoCorrection(const OUString &rOld, const OUString &rNew, LanguageType eLanguage) override
virtual const tools::Rectangle & GetLogicRect() const override
Base class of the Writer document model elements.
Definition: node.hxx:80
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo