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 <svx/svxids.hrc>
27 #include <sfx2/app.hxx>
28 #include <sfx2/bindings.hxx>
29 #include <sfx2/dispatch.hxx>
30 #include <sfx2/viewfrm.hxx>
31 #include <editeng/unolingu.hxx>
32 #include <editeng/editeng.hxx>
33 #include <editeng/editview.hxx>
34 #include <wrtsh.hxx>
35 #include <sfx2/printer.hxx>
36 #include <svx/svdoutl.hxx>
37 #include <svx/svdview.hxx>
38 #include <svx/svditer.hxx>
39 #include <svx/svdogrp.hxx>
40 #include <unotools/linguprops.hxx>
41 #include <unotools/lingucfg.hxx>
42 #include <doc.hxx>
45 #include <docsh.hxx>
46 #include <docary.hxx>
47 #include <drawdoc.hxx>
48 #include <frmfmt.hxx>
49 #include <dcontact.hxx>
50 #include <edtwin.hxx>
51 #include <pam.hxx>
52 #include <drawbase.hxx>
53 #include <unotextrange.hxx>
54 #include <strings.hrc>
55 #include <cmdid.h>
56 
57 using namespace ::com::sun::star;
58 using namespace ::com::sun::star::uno;
59 using namespace ::com::sun::star::text;
60 using namespace ::com::sun::star::linguistic2;
61 using namespace ::com::sun::star::beans;
62 
64 
65 struct SpellState
66 {
68  bool m_bLockFocus; // lock the focus notification while a modal dialog is active
70 
71  // restart and progress information
72  bool m_bBodySpelled; // body already spelled
73  bool m_bOtherSpelled; // frames, footnotes, headers and footers spelled
74  bool m_bStartedInOther; // started the spelling inside of the _other_ area
75  bool m_bStartedInSelection; // there was an initial text selection
76  std::unique_ptr<SwPaM>
77  pOtherCursor; // position where the spelling inside the _other_ area started
78  bool m_bDrawingsSpelled; // all drawings spelled
79  Reference<XTextRange> m_xStartRange; // text range that marks the start of spelling
80  const SdrObject* m_pStartDrawing; // draw text object spelling started in
81  ESelection m_aStartDrawingSelection; // draw text start selection
82  bool m_bRestartDrawing; // the first selected drawing object is found again
83 
84  // lose/get focus information to decide if spelling can be continued
88  sal_Int32 m_nPointPos;
89  sal_Int32 m_nMarkPos;
92 
93  // iterating over draw text objects
94  std::list<SdrTextObj*> m_aTextObjects;
96 
98  m_bInitialCall(true),
99  m_bLockFocus(false),
100  m_bLostFocus(false),
101  m_bBodySpelled(false),
102  m_bOtherSpelled(false),
103  m_bStartedInOther(false),
104  m_bStartedInSelection(false),
105  m_bDrawingsSpelled(false),
106  m_pStartDrawing(nullptr),
107  m_bRestartDrawing(false),
108 
109  m_eSelMode(ShellMode::Object), // initially invalid
110  m_pPointNode(nullptr),
111  m_pMarkNode(nullptr),
112  m_nPointPos(0),
113  m_nMarkPos(0),
114  m_pOutliner(nullptr),
115  m_bTextObjectsCollected(false)
116  {}
117 
118  // reset state in ::InvalidateSpellDialog
119  void Reset()
120  { m_bInitialCall = true;
121  m_bBodySpelled = m_bOtherSpelled = m_bDrawingsSpelled = false;
122  m_xStartRange = nullptr;
123  m_pStartDrawing = nullptr;
124  m_bRestartDrawing = false;
125  m_bTextObjectsCollected = false;
126  m_aTextObjects.clear();
127  m_bStartedInOther = false;
128  pOtherCursor.reset();
129  }
130 };
131 
132 static void lcl_LeaveDrawText(SwWrtShell& rSh)
133 {
134  if(rSh.GetDrawView())
135  {
136  rSh.GetDrawView()->SdrEndTextEdit( true );
137  Point aPt(LONG_MIN, LONG_MIN);
138  // go out of the frame
139  rSh.SelectObj(aPt, SW_LEAVE_FRAME);
140  rSh.EnterStdMode();
141  rSh.GetView().AttrChangedNotify(&rSh);
142  }
143 }
144 
146  vcl::Window* _pParent,
147  sal_uInt16 nId,
148  SfxBindings* pBindings,
149  SfxChildWinInfo* /*pInfo*/)
150  : svx::SpellDialogChildWindow (
151  _pParent, nId, pBindings)
152  , m_bIsGrammarCheckingOn(false)
153  , m_pSpellState(new SpellState)
154 {
156 }
157 
159 {
160  SwWrtShell* pWrtShell = GetWrtShell_Impl();
161  if(!m_pSpellState->m_bInitialCall && pWrtShell)
162  pWrtShell->SpellEnd();
163  m_pSpellState.reset();
164 }
165 
166 SfxChildWinInfo SwSpellDialogChildWindow::GetInfo() const
167 {
168  SfxChildWinInfo aInfo = svx::SpellDialogChildWindow::GetInfo();
169  aInfo.bVisible = false;
170  return aInfo;
171 }
172 
174 {
175  svx::SpellPortions aRet;
176  SwWrtShell* pWrtShell = GetWrtShell_Impl();
177  if(pWrtShell)
178  {
179  if (!bRecheck)
180  {
181  // first set continuation point for spell/grammar check to the
182  // end of the current sentence
184  }
185 
186  ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
187  bool bDrawText = ShellMode::DrawText == eSelMode;
188  bool bNormalText =
189  ShellMode::TableText == eSelMode ||
190  ShellMode::ListText == eSelMode ||
191  ShellMode::TableListText == eSelMode ||
192  ShellMode::Text == eSelMode;
193  // Writer text outside of the body
194  bool bOtherText = false;
195 
196  if( m_pSpellState->m_bInitialCall )
197  {
198  // if no text selection exists the cursor has to be set into the text
199  if(!bDrawText && !bNormalText)
200  {
201  MakeTextSelection_Impl(*pWrtShell, eSelMode);
202  // the selection type has to be checked again - both text types are possible
204  bDrawText = true;
205  bNormalText = !bDrawText;
206  }
207  if(bNormalText)
208  {
209  // set cursor to the start of the sentence
210  if(!pWrtShell->HasSelection())
211  pWrtShell->GoStartSentence();
212  else
213  {
214  pWrtShell->ExpandToSentenceBorders();
215  m_pSpellState->m_bStartedInSelection = true;
216  }
217  // determine if the selection is outside of the body text
218  bOtherText = !(pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY);
219  if(bOtherText)
220  {
221  m_pSpellState->pOtherCursor.reset( new SwPaM(*pWrtShell->GetCursor()->GetPoint()) );
222  m_pSpellState->m_bStartedInOther = true;
224  }
225  else
226  {
227  // mark the start position only if not at start of doc
228  if(!pWrtShell->IsStartOfDoc())
229  {
230  // Record the position *before* the current cursor, as
231  // the word at the current cursor can possibly be
232  // replaced by a spellcheck correction which invalidates
233  // an XTextRange at this position.
234  SwDoc *pDoc = pWrtShell->GetDoc();
235  auto pStart = pWrtShell->GetCursor()->Start();
236  auto pUnoCursor = pDoc->CreateUnoCursor(*pStart);
237  pUnoCursor->Left( 1 );
238  pStart = pUnoCursor->Start();
239  m_pSpellState->m_xStartRange
240  = SwXTextRange::CreateXTextRange(*pDoc, *pStart, nullptr);
241  }
243  }
244  }
245  else
246  {
247  SdrView* pSdrView = pWrtShell->GetDrawView();
248  m_pSpellState->m_pStartDrawing = pSdrView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
249  OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
250  // start checking at the top of the drawing object
251  pOLV->SetSelection( ESelection() );
252  m_pSpellState->m_aStartDrawingSelection = ESelection();
253 /*
254 Note: spelling in a selection only, or starting in a mid of a drawing object requires
255 further changes elsewhere. (Especially if it should work in sc and sd as well.)
256 The code below would only be part of the solution.
257 (Keeping it a as a comment for the time being)
258  ESelection aCurSel( pOLV->GetSelection() );
259  ESelection aSentenceSel( pOLV->GetEditView().GetEditEngine()->SelectSentence( aCurSel ) );
260  if (!aCurSel.HasRange())
261  {
262  aSentenceSel.nEndPara = aSentenceSel.nStartPara;
263  aSentenceSel.nEndPos = aSentenceSel.nStartPos;
264  }
265  pOLV->SetSelection( aSentenceSel );
266  m_pSpellState->m_aStartDrawingSelection = aSentenceSel;
267 */
268  }
269 
270  m_pSpellState->m_bInitialCall = false;
271  }
272  if( bDrawText )
273  {
274  // spell inside of the current draw text
275  if(!SpellDrawText_Impl(*pWrtShell, aRet))
276  {
277  if(!FindNextDrawTextError_Impl(*pWrtShell) || !SpellDrawText_Impl(*pWrtShell, aRet))
278  {
279  lcl_LeaveDrawText(*pWrtShell);
280  // now the drawings have been spelled
281  m_pSpellState->m_bDrawingsSpelled = true;
282  // the spelling continues at the other content
283  // if there's any that has not been spelled yet
284  if(!m_pSpellState->m_bOtherSpelled && pWrtShell->HasOtherCnt())
285  {
287  if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
288  {
289  pWrtShell->SpellEnd();
290  m_pSpellState->m_bOtherSpelled = true;
291  }
292  }
293  else
294  m_pSpellState->m_bOtherSpelled = true;
295  // if no result has been found try at the body text - completely
296  if(!m_pSpellState->m_bBodySpelled && aRet.empty())
297  {
299  if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
300  {
301  m_pSpellState->m_bBodySpelled = true;
302  pWrtShell->SpellEnd();
303  }
304  }
305 
306  }
307  }
308  }
309  else
310  {
311  // spell inside of the Writer text
312  if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
313  {
314  // if there is a selection (within body or header/footer text)
315  // then spell/grammar checking should not move outside of it.
316  if (!m_pSpellState->m_bStartedInSelection)
317  {
318  // find out which text has been spelled body or other
319  bOtherText = !(pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY);
320  if(bOtherText && m_pSpellState->m_bStartedInOther && m_pSpellState->pOtherCursor)
321  {
322  m_pSpellState->m_bStartedInOther = false;
323  pWrtShell->SetSelection(*m_pSpellState->pOtherCursor);
324  pWrtShell->SpellEnd();
325  m_pSpellState->pOtherCursor.reset();
327  (void)pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn);
328  }
329  if(aRet.empty())
330  {
331  // end spelling
332  pWrtShell->SpellEnd();
333  if(bOtherText)
334  {
335  m_pSpellState->m_bOtherSpelled = true;
336  // has the body been spelled?
337  if(!m_pSpellState->m_bBodySpelled)
338  {
340  if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
341  {
342  m_pSpellState->m_bBodySpelled = true;
343  pWrtShell->SpellEnd();
344  }
345  }
346  }
347  else
348  {
349  m_pSpellState->m_bBodySpelled = true;
350  if(!m_pSpellState->m_bOtherSpelled && pWrtShell->HasOtherCnt())
351  {
353  if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
354  {
355  pWrtShell->SpellEnd();
356  m_pSpellState->m_bOtherSpelled = true;
357  }
358  }
359  else
360  m_pSpellState->m_bOtherSpelled = true;
361  }
362  }
363 
364  // search for a draw text object that contains error and spell it
365  if(aRet.empty() &&
366  (m_pSpellState->m_bDrawingsSpelled ||
367  !FindNextDrawTextError_Impl(*pWrtShell) || !SpellDrawText_Impl(*pWrtShell, aRet)))
368  {
369  lcl_LeaveDrawText(*pWrtShell);
370  m_pSpellState->m_bDrawingsSpelled = true;
371  }
372  }
373  }
374  }
375  // now only the rest of the body text can be spelled -
376  // if the spelling started inside of the body
377  bool bCloseMessage = true;
378  if(aRet.empty() && !m_pSpellState->m_bStartedInSelection)
379  {
380  OSL_ENSURE(m_pSpellState->m_bDrawingsSpelled &&
381  m_pSpellState->m_bOtherSpelled && m_pSpellState->m_bBodySpelled,
382  "not all parts of the document are already spelled");
383  if(m_pSpellState->m_xStartRange.is())
384  {
385  LockFocusNotification( true );
386  std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetWindow()->GetFrameWeld(),
387  VclMessageType::Question, VclButtonsType::YesNo, SwResId(STR_QUERY_SPELL_CONTINUE)));
388  sal_uInt16 nRet = xBox->run();
389  if (RET_YES == nRet)
390  {
391  SwUnoInternalPaM aPam(*pWrtShell->GetDoc());
392  if (::sw::XTextRangeToSwPaM(aPam,
393  m_pSpellState->m_xStartRange))
394  {
395  pWrtShell->SetSelection(aPam);
397  if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
398  pWrtShell->SpellEnd();
399  }
400  m_pSpellState->m_xStartRange = nullptr;
401  LockFocusNotification( false );
402  // take care that the now valid selection is stored
403  LoseFocus();
404  }
405  else
406  bCloseMessage = false; // no closing message if a wrap around has been denied
407  }
408  }
409  bool bNoDictionaryAvailable = pWrtShell->GetDoc()->IsDictionaryMissing();
410  if( aRet.empty() && bCloseMessage )
411  {
412  LockFocusNotification( true );
413  OUString sInfo( SwResId( bNoDictionaryAvailable ? STR_DICTIONARY_UNAVAILABLE : STR_SPELLING_COMPLETED ) );
414  vcl::Window* pThisWindow = GetWindow();
415  // #i84610#
416  std::unique_ptr<weld::MessageDialog> xBox(
418  VclMessageType::Info,
419  VclButtonsType::Ok,
420  sInfo ) );
421  xBox->run();
422  LockFocusNotification( false );
423  // take care that the now valid selection is stored
424  LoseFocus();
425  if( pThisWindow )
426  pThisWindow->GrabFocus();
427  }
428  }
429  return aRet;
430 }
431 
433 {
434  SwWrtShell* pWrtShell = GetWrtShell_Impl();
435  OSL_ENSURE(!m_pSpellState->m_bInitialCall, "ApplyChangedSentence in initial call or after resume");
436  if(pWrtShell && !m_pSpellState->m_bInitialCall)
437  {
438  ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
439  bool bDrawText = ShellMode::DrawText == eSelMode;
440  bool bNormalText =
441  ShellMode::TableText == eSelMode ||
442  ShellMode::ListText == eSelMode ||
443  ShellMode::TableListText == eSelMode ||
444  ShellMode::Text == eSelMode;
445 
446  // evaluate if the same sentence should be rechecked or not.
447  // Sentences that got grammar checked should always be rechecked in order
448  // to detect possible errors that get introduced with the changes
450 
451  if(bNormalText)
452  pWrtShell->ApplyChangedSentence(rChanged, bRecheck);
453  else if(bDrawText )
454  {
455  SdrView* pDrView = pWrtShell->GetDrawView();
456  SdrOutliner *pOutliner = pDrView->GetTextEditOutliner();
457  pOutliner->ApplyChangedSentence(pDrView->GetTextEditOutlinerView()->GetEditView(), rChanged, bRecheck);
458  }
459  }
460 }
461 
463  const OUString& rOld, const OUString& rNew, LanguageType eLanguage)
464 {
466  pACorr->PutText( rOld, rNew, eLanguage );
467 }
468 
470 {
471  return true;
472 }
473 
475 {
477 }
478 
480 {
481  return m_bIsGrammarCheckingOn;
482 }
483 
485 {
486  uno::Any aVal;
487  aVal <<= bOn;
490  // set current spell position to the start of the current sentence to
491  // continue with this sentence after grammar checking state has been changed
492  SwWrtShell* pWrtShell = GetWrtShell_Impl();
493  if(pWrtShell)
494  {
495  ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
496  bool bDrawText = ShellMode::DrawText == eSelMode;
497  bool bNormalText =
498  ShellMode::TableText == eSelMode ||
499  ShellMode::ListText == eSelMode ||
500  ShellMode::TableListText == eSelMode ||
501  ShellMode::Text == eSelMode;
502  if( bNormalText )
504  else if( bDrawText )
505  {
506  SdrView* pSdrView = pWrtShell->GetDrawView();
507  SdrOutliner* pOutliner = pSdrView ? pSdrView->GetTextEditOutliner() : nullptr;
508  OSL_ENSURE(pOutliner, "No Outliner in SwSpellDialogChildWindow::SetGrammarChecking");
509  if(pOutliner)
510  {
511  pOutliner->PutSpellingToSentenceStart( pSdrView->GetTextEditOutlinerView()->GetEditView() );
512  }
513  }
514  }
515 }
516 
518 {
519  if(m_pSpellState->m_bLockFocus)
520  return;
521  bool bInvalidate = false;
522  SwWrtShell* pWrtShell = GetWrtShell_Impl();
523  if(pWrtShell && !m_pSpellState->m_bInitialCall)
524  {
525  ShellMode eSelMode = pWrtShell->GetView().GetShellMode();
526  if(eSelMode != m_pSpellState->m_eSelMode)
527  {
528  // prevent initial invalidation
529  if(m_pSpellState->m_bLostFocus)
530  bInvalidate = true;
531  }
532  else
533  {
534  switch(m_pSpellState->m_eSelMode)
535  {
536  case ShellMode::Text:
537  case ShellMode::ListText:
540  {
541  SwPaM* pCursor = pWrtShell->GetCursor();
542  if(m_pSpellState->m_pPointNode != &pCursor->GetNode() ||
543  m_pSpellState->m_pMarkNode != &pCursor->GetNode(false)||
544  m_pSpellState->m_nPointPos != pCursor->GetPoint()->nContent.GetIndex()||
545  m_pSpellState->m_nMarkPos != pCursor->GetMark()->nContent.GetIndex())
546  bInvalidate = true;
547  }
548  break;
549  case ShellMode::DrawText:
550  {
551  SdrView* pSdrView = pWrtShell->GetDrawView();
552  SdrOutliner* pOutliner = pSdrView ? pSdrView->GetTextEditOutliner() : nullptr;
553  if(!pOutliner || m_pSpellState->m_pOutliner != pOutliner)
554  bInvalidate = true;
555  else
556  {
557  OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
558  OSL_ENSURE(pOLV, "no OutlinerView in SwSpellDialogChildWindow::GetFocus()");
559  if(!pOLV || m_pSpellState->m_aESelection != pOLV->GetSelection())
560  bInvalidate = true;
561  }
562  }
563  break;
564  default: bInvalidate = true;
565  }
566  }
567  }
568  else
569  {
570  bInvalidate = true;
571  }
572  if(bInvalidate)
574 }
575 
577 {
578  // prevent initial invalidation
579  m_pSpellState->m_bLostFocus = true;
580  if(m_pSpellState->m_bLockFocus)
581  return;
582  SwWrtShell* pWrtShell = GetWrtShell_Impl();
583  if(pWrtShell)
584  {
585  m_pSpellState->m_eSelMode = pWrtShell->GetView().GetShellMode();
586  m_pSpellState->m_pPointNode = m_pSpellState->m_pMarkNode = nullptr;
587  m_pSpellState->m_nPointPos = m_pSpellState->m_nMarkPos = 0;
588  m_pSpellState->m_pOutliner = nullptr;
589 
590  switch(m_pSpellState->m_eSelMode)
591  {
592  case ShellMode::Text:
593  case ShellMode::ListText:
596  {
597  // store a node pointer and a pam-position to be able to check on next GetFocus();
598  SwPaM* pCursor = pWrtShell->GetCursor();
599  m_pSpellState->m_pPointNode = &pCursor->GetNode();
600  m_pSpellState->m_pMarkNode = &pCursor->GetNode(false);
601  m_pSpellState->m_nPointPos = pCursor->GetPoint()->nContent.GetIndex();
602  m_pSpellState->m_nMarkPos = pCursor->GetMark()->nContent.GetIndex();
603 
604  }
605  break;
606  case ShellMode::DrawText:
607  {
608  SdrView* pSdrView = pWrtShell->GetDrawView();
609  SdrOutliner* pOutliner = pSdrView->GetTextEditOutliner();
610  m_pSpellState->m_pOutliner = pOutliner;
611  OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
612  OSL_ENSURE(pOutliner && pOLV, "no Outliner/OutlinerView in SwSpellDialogChildWindow::LoseFocus()");
613  if(pOLV)
614  {
615  m_pSpellState->m_aESelection = pOLV->GetSelection();
616  }
617  }
618  break;
619  default:;// prevent warning
620  }
621  }
622  else
623  m_pSpellState->m_eSelMode = ShellMode::Object;
624 }
625 
627 {
628  SwWrtShell* pWrtShell = GetWrtShell_Impl();
629  if(!m_pSpellState->m_bInitialCall && pWrtShell)
630  pWrtShell->SpellEnd(nullptr, false);
631  m_pSpellState->Reset();
633 }
634 
636 {
637  SfxDispatcher* pDispatch = GetBindings().GetDispatcher();
638  SwView* pView = nullptr;
639  if(pDispatch)
640  {
641  sal_uInt16 nShellIdx = 0;
642  SfxShell* pShell;
643  while(nullptr != (pShell = pDispatch->GetShell(nShellIdx++)))
644  if(dynamic_cast< const SwView *>( pShell ) != nullptr)
645  {
646  pView = static_cast<SwView* >(pShell);
647  break;
648  }
649  }
650  return pView ? pView->GetWrtShellPtr(): nullptr;
651 }
652 
653 // set the cursor into the body text - necessary if any object is selected
654 // on start of the spelling dialog
656 {
657  SwView& rView = rShell.GetView();
658  switch(eSelMode)
659  {
660  case ShellMode::Text:
661  case ShellMode::ListText:
664  case ShellMode::DrawText:
665  OSL_FAIL("text already active in SwSpellDialogChildWindow::MakeTextSelection_Impl()");
666  break;
667 
668  case ShellMode::Frame:
669  {
670  rShell.UnSelectFrame();
671  rShell.LeaveSelFrameMode();
672  rView.AttrChangedNotify(&rShell);
673  }
674  break;
675 
676  case ShellMode::Draw:
677  case ShellMode::DrawForm:
678  case ShellMode::Bezier:
679  if(FindNextDrawTextError_Impl(rShell))
680  {
681  rView.AttrChangedNotify(&rShell);
682  break;
683  }
684  [[fallthrough]]; // to deselect the object
685  case ShellMode::Graphic:
686  case ShellMode::Object:
687  {
688  if ( rShell.IsDrawCreate() )
689  {
690  rView.GetDrawFuncPtr()->BreakCreate();
691  rView.AttrChangedNotify(&rShell);
692  }
693  else if ( rShell.HasSelection() || rView.IsDrawMode() )
694  {
695  SdrView *pSdrView = rShell.GetDrawView();
696  if(pSdrView && pSdrView->AreObjectsMarked() &&
697  pSdrView->GetHdlList().GetFocusHdl())
698  {
699  const_cast<SdrHdlList&>(pSdrView->GetHdlList()).ResetFocusHdl();
700  }
701  else
702  {
703  rView.LeaveDrawCreate();
704  Point aPt(LONG_MIN, LONG_MIN);
705  // go out of the frame
706  rShell.SelectObj(aPt, SW_LEAVE_FRAME);
707  SfxBindings& rBind = rView.GetViewFrame()->GetBindings();
708  rBind.Invalidate( SID_ATTR_SIZE );
709  rShell.EnterStdMode();
710  rView.AttrChangedNotify(&rShell);
711  }
712  }
713  }
714  break;
715  default:; // prevent warning
716  }
717 }
718 
719 // select the next draw text object that has a spelling error
721 {
722  bool bNextDoc = false;
723  SdrView* pDrView = rSh.GetDrawView();
724  if(!pDrView)
725  return bNextDoc;
726  SwView& rView = rSh.GetView();
727  SwDoc* pDoc = rView.GetDocShell()->GetDoc();
728  const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
729  // start at the current draw object - if there is any selected
730  SdrTextObj* pCurrentTextObj = nullptr;
731  if ( rMarkList.GetMarkCount() == 1 )
732  {
733  SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
734  if( auto pSdrTextObj = dynamic_cast<SdrTextObj *>( pObj ) )
735  pCurrentTextObj = pSdrTextObj;
736  }
737  // at first fill the list of drawing objects
738  if(!m_pSpellState->m_bTextObjectsCollected )
739  {
740  m_pSpellState->m_bTextObjectsCollected = true;
742  if(pCurrentTextObj)
743  {
744  m_pSpellState->m_aTextObjects.remove(pCurrentTextObj);
745  m_pSpellState->m_aTextObjects.push_back(pCurrentTextObj);
746  }
747  }
748  if(!m_pSpellState->m_aTextObjects.empty())
749  {
750  Reference< XSpellChecker1 > xSpell( GetSpellChecker() );
751  while(!bNextDoc && !m_pSpellState->m_aTextObjects.empty())
752  {
753  std::list<SdrTextObj*>::iterator aStart = m_pSpellState->m_aTextObjects.begin();
754  SdrTextObj* pTextObj = *aStart;
755  if(m_pSpellState->m_pStartDrawing == pTextObj)
756  m_pSpellState->m_bRestartDrawing = true;
757  m_pSpellState->m_aTextObjects.erase(aStart);
758  OutlinerParaObject* pParaObj = pTextObj->GetOutlinerParaObject();
759  if ( pParaObj )
760  {
761  bool bHasSpellError = false;
762  {
763  SdrOutliner aTmpOutliner(pDoc->getIDocumentDrawModelAccess().GetDrawModel()->
764  GetDrawOutliner().GetEmptyItemSet().GetPool(),
765  OutlinerMode::TextObject );
766  aTmpOutliner.SetRefDevice( pDoc->getIDocumentDeviceAccess().getPrinter( false ) );
767  MapMode aMapMode (MapUnit::MapTwip);
768  aTmpOutliner.SetRefMapMode(aMapMode);
769  aTmpOutliner.SetPaperSize( pTextObj->GetLogicRect().GetSize() );
770  aTmpOutliner.SetSpeller( xSpell );
771 
772  std::unique_ptr<OutlinerView> pOutlView( new OutlinerView( &aTmpOutliner, &(rView.GetEditWin()) ) );
773  pOutlView->GetOutliner()->SetRefDevice( rSh.getIDocumentDeviceAccess().getPrinter( false ) );
774  aTmpOutliner.InsertView( pOutlView.get() );
775  Size aSize(1,1);
776  tools::Rectangle aRect( Point(), aSize );
777  pOutlView->SetOutputArea( aRect );
778  aTmpOutliner.SetText( *pParaObj );
779  aTmpOutliner.ClearModifyFlag();
780  bHasSpellError = EESpellState::Ok != aTmpOutliner.HasSpellErrors();
781  aTmpOutliner.RemoveView( pOutlView.get() );
782  }
783  if(bHasSpellError)
784  {
785  // now the current one has to be deselected
786  if(pCurrentTextObj)
787  pDrView->SdrEndTextEdit( true );
788  // and the found one should be activated
789  rSh.MakeVisible(pTextObj->GetLogicRect());
790  Point aTmp( 0,0 );
791  rSh.SelectObj( aTmp, 0, pTextObj );
792  SdrPageView* pPV = pDrView->GetSdrPageView();
793  rView.BeginTextEdit( pTextObj, pPV, &rView.GetEditWin(), false, true );
794  rView.AttrChangedNotify(&rSh);
795  bNextDoc = true;
796  }
797  }
798  }
799  }
800  return bNextDoc;
801 }
802 
804 {
805  bool bRet = false;
806  SdrView* pSdrView = rSh.GetDrawView();
807  SdrOutliner* pOutliner = pSdrView ? pSdrView->GetTextEditOutliner() : nullptr;
808  OSL_ENSURE(pOutliner, "No Outliner in SwSpellDialogChildWindow::SpellDrawText_Impl");
809  if(pOutliner)
810  {
811  bRet = pOutliner->SpellSentence(pSdrView->GetTextEditOutlinerView()->GetEditView(), rPortions);
812  // find out if the current selection is in the first spelled drawing object
813  // and behind the initial selection
814  if(bRet && m_pSpellState->m_bRestartDrawing)
815  {
816  OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
817  ESelection aCurrentSelection = pOLV->GetSelection();
818  if(m_pSpellState->m_aStartDrawingSelection.nEndPara < aCurrentSelection.nEndPara ||
819  (m_pSpellState->m_aStartDrawingSelection.nEndPara == aCurrentSelection.nEndPara &&
820  m_pSpellState->m_aStartDrawingSelection.nEndPos < aCurrentSelection.nEndPos))
821  {
822  bRet = false;
823  rPortions.clear();
824  }
825  }
826  }
827  return bRet;
828 }
829 
831 {
832  OSL_ENSURE(m_pSpellState->m_bLockFocus != bLock, "invalid locking - no change of state");
833  m_pSpellState->m_bLockFocus = bLock;
834 }
835 
836 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SfxViewFrame * GetViewFrame() const
std::shared_ptr< SwUnoCursor > CreateUnoCursor(const SwPosition &rPos, bool bTableCursor=false)
Definition: doc.cxx:1785
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)
SdrView * GetDrawView()
Definition: vnew.cxx:376
const SwNode * m_pMarkNode
SwPaM * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:185
bool IsDrawMode()
Definition: view.hxx:526
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:270
bool AreObjectsMarked() const
bool IsStartOfDoc() const
Definition: crsrsh.cxx:2632
static bool HasLastSentenceGotGrammarChecked()
Check SwSpellIter data to see if the last sentence got grammar checked.
Definition: edlingu.cxx:582
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:1029
Definition: doc.hxx:185
ShellMode GetShellMode()
Definition: view0.cxx:114
void EnterStdMode()
Definition: select.cxx:552
SwEditWin & GetEditWin()
Definition: view.hxx:403
SdrMark * GetMark(size_t nNum) const
const SdrObject * m_pStartDrawing
Reference< XTextRange > m_xStartRange
void ApplyChangedSentence(const svx::SpellPortions &rNewPortions, bool bRecheck)
Applies a changed sentence.
Definition: edlingu.cxx:1068
void Invalidate(sal_uInt16 nId)
IDocumentDrawModelAccess const & getIDocumentDrawModelAccess() const
Definition: doc.cxx:187
bool GoStartSentence()
Definition: crstrvl1.cxx:78
Used by the UI to modify the document model.
Definition: wrtsh.hxx:86
weld::Window * GetFrameWeld() const
void BreakCreate()
Definition: drawbase.cxx:466
std::unique_ptr< SpellState > m_pSpellState
const SwView & GetView() const
Definition: wrtsh.hxx:424
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:284
bool SpellDrawText_Impl(SwWrtShell &rSh, svx::SpellPortions &rPortions)
sal_Int32 nEndPos
ShellMode
Definition: view.hxx:87
bool XTextRangeToSwPaM(SwUnoInternalPaM &rToFill, const uno::Reference< text::XTextRange > &xTextRange)
Definition: unoobj2.cxx:1031
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:202
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:2590
bool HasOtherCnt() const
Are there frames, footnotes, etc.
Definition: edws.cxx:143
sal_Int32 nEndPara
const SdrOutliner * GetTextEditOutliner() const
bool HasSelection() const
Definition: wrtsh.hxx:137
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:655
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:3393
weld::Window * GetFrameWeld(SfxFrame *pFrame)
Definition: dialoghelp.cxx:20
SFX_IMPL_CHILDWINDOW_WITHID(SearchResultsDlgWrapper, SID_SEARCH_RESULTS_DIALOG)
const OutlinerView * GetTextEditOutlinerView() const
OUString SwResId(const char *pId)
Definition: swmodule.cxx:191
virtual bool HasAutoCorrection() override
void LeaveDrawCreate()
Definition: view.hxx:525
SwDrawBase * GetDrawFuncPtr() const
Definition: view.hxx:513
virtual void SetGrammarChecking(bool bOn) override
void GrabFocus()
virtual SfxPrinter * getPrinter(bool bCreate) const =0
Return the printer set at the document.
Size GetSize() const
const SwPosition * Start() const
Definition: pam.hxx:212
SwDocShell * GetDocShell()
Definition: view.cxx:1115
static void MoveContinuationPosToEndOfCheckedSentence()
Moves the continuation position to the end of the currently checked sentence.
Definition: edlingu.cxx:1058
SdrHdl * GetFocusHdl() const
const SwNode * m_pPointNode
void SetSelection(const ESelection &)
SwWrtShell * GetWrtShellPtr() const
Definition: view.hxx:401
bool PutText(const OUString &rShort, const OUString &rLong, LanguageType eLang)
#define FN_SPELL_GRAMMAR_DIALOG
Definition: cmdid.h:579
virtual OutlinerParaObject * GetOutlinerParaObject() const override
bool IsDictionaryMissing()
Returns true if no dictionary can be found for any content.
Definition: doc.hxx:1647
sal_Int32 GetIndex() const
Definition: index.hxx:95
uno::Reference< linguistic2::XSpellChecker1 > GetSpellChecker()
Definition: swtypes.cxx:66
void SpellStart(SwDocPositions eStart, SwDocPositions eEnd, SwDocPositions eCurr, SwConversionArgs *pConvArgs=nullptr)
Functions used for spell checking and text conversion.
Definition: edlingu.cxx:618
bool SetProperty(const OUString &rPropertyName, const css::uno::Any &rValue)
void UnSelectFrame()
Definition: select.cxx:327
bool SelectObj(const Point &rSelPt, sal_uInt8 nFlag=0, SdrObject *pObj=nullptr)
If an object as been given, exactly this object is selected (instead of searching over position)...
Definition: feshview.cxx:185
ESelection GetSelection()
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage)
SdrPageView * GetSdrPageView() const
void LeaveSelFrameMode()
Definition: select.cxx:721
static void lcl_LeaveDrawText(SwWrtShell &rSh)
SfxDispatcher * GetDispatcher() const
static void GetTextObjectsFromFormat(std::list< SdrTextObj * > &, SwDoc *)
get data collection of anchored objects, handled by with contact
Definition: dcontact.cxx:735
static void PutSpellingToSentenceStart()
Make SpellIter start with the current sentence when called next time.
Definition: edlingu.cxx:1044
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:1135
SelectionType GetSelectionType() const
Definition: wrtsh1.cxx:1373
bool IsDrawCreate() const
Definition: feshview.cxx:2148
FrameTypeFlags GetFrameType(const Point *pPt, bool bStopAtFly) const
For return values see above FrameType.
Definition: fews.cxx:238
std::list< SdrTextObj * > m_aTextObjects
Definition: view.hxx:146
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:79
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo