LibreOffice Module sw (master)  1
edlingu.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 <com/sun/star/linguistic2/ProofreadingResult.hpp>
21 #include <com/sun/star/linguistic2/XProofreadingIterator.hpp>
22 #include <com/sun/star/linguistic2/XHyphenatedWord.hpp>
23 #include <com/sun/star/linguistic2/XLinguProperties.hpp>
24 #include <com/sun/star/text/XFlatParagraph.hpp>
25 #include <com/sun/star/i18n/ScriptType.hpp>
26 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <o3tl/any.hxx>
28 
29 #include <unoflatpara.hxx>
30 
31 #include <strings.hrc>
32 #include <hintids.hxx>
33 #include <unotools/linguprops.hxx>
34 #include <linguistic/lngprops.hxx>
35 #include <editeng/unolingu.hxx>
36 #include <editeng/svxacorr.hxx>
37 #include <editeng/langitem.hxx>
40 #include <charatr.hxx>
41 #include <editsh.hxx>
42 #include <doc.hxx>
43 #include <IDocumentUndoRedo.hxx>
45 #include <rootfrm.hxx>
46 #include <pam.hxx>
47 #include <pamtyp.hxx>
48 #include <swundo.hxx>
49 #include <ndtxt.hxx>
50 #include <viewopt.hxx>
51 #include <viscrs.hxx>
52 #include <SwGrammarMarkUp.hxx>
53 #include <mdiexp.hxx>
54 #include <cntfrm.hxx>
55 #include <splargs.hxx>
56 #include <redline.hxx>
57 #include <docary.hxx>
58 #include <docsh.hxx>
59 #include <txatbase.hxx>
60 #include <txtfrm.hxx>
61 
62 using namespace ::svx;
63 using namespace ::com::sun::star;
64 using namespace ::com::sun::star::uno;
65 using namespace ::com::sun::star::beans;
66 using namespace ::com::sun::star::linguistic2;
67 
69 {
71  std::unique_ptr<SwPosition> m_pStart;
72  std::unique_ptr<SwPosition> m_pEnd;
73  std::unique_ptr<SwPosition> m_pCurr;
74  std::unique_ptr<SwPosition> m_pCurrX;
75  sal_uInt16 nCursorCnt;
76 public:
77  SwLinguIter();
78 
79  SwEditShell *GetSh() { return pSh; }
80 
81  const SwPosition *GetEnd() const { return m_pEnd.get(); }
82  void SetEnd(SwPosition* pNew) { m_pEnd.reset(pNew); }
83 
84  const SwPosition *GetStart() const { return m_pStart.get(); }
85  void SetStart(SwPosition* pNew) { m_pStart.reset(pNew); }
86 
87  const SwPosition *GetCurr() const { return m_pCurr.get(); }
88  void SetCurr(SwPosition* pNew) { m_pCurr.reset(pNew); }
89 
90  const SwPosition *GetCurrX() const { return m_pCurrX.get(); }
91  void SetCurrX(SwPosition* pNew) { m_pCurrX.reset(pNew); }
92 
93  sal_uInt16& GetCursorCnt(){ return nCursorCnt; }
94 
95  // for the UI:
96  void Start_( SwEditShell *pSh, SwDocPositions eStart,
97  SwDocPositions eEnd );
98  void End_(bool bRestoreSelection = true);
99 };
100 
101 // #i18881# to be able to identify the positions of the changed words
102 // the content positions of each portion need to be saved
104 {
105  sal_Int32 nLeft;
106  sal_Int32 nRight;
107 };
108 
109 typedef std::vector<SpellContentPosition> SpellContentPositions;
110 
111 class SwSpellIter : public SwLinguIter
112 {
113  uno::Reference< XSpellChecker1 > xSpeller;
115 
118 
119  void CreatePortion(uno::Reference< XSpellAlternatives > const & xAlt,
120  linguistic2::ProofreadingResult* pGrammarResult,
121  bool bIsField, bool bIsHidden);
122 
123  void AddPortion(uno::Reference< XSpellAlternatives > const & xAlt,
124  linguistic2::ProofreadingResult* pGrammarResult,
125  const SpellContentPositions& rDeletedRedlines);
126 public:
128  bBackToStartOfSentence(false) {}
129 
130  void Start( SwEditShell *pSh, SwDocPositions eStart, SwDocPositions eEnd );
131 
132  uno::Any Continue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt );
133 
134  bool SpellSentence(svx::SpellPortions& rPortions, bool bIsGrammarCheck);
135  void ToSentenceStart();
138 };
139 
141 class SwConvIter : public SwLinguIter
142 {
144 public:
145  explicit SwConvIter(SwConversionArgs &rConvArgs)
146  : rArgs(rConvArgs)
147  {
148  }
149 
150  void Start( SwEditShell *pSh, SwDocPositions eStart, SwDocPositions eEnd );
151 
152  uno::Any Continue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt );
153 };
154 
155 class SwHyphIter : public SwLinguIter
156 {
157  // With that we save a GetFrame() in Hyphenate //TODO: does it actually matter?
160  friend SwTextFrame * sw::SwHyphIterCacheLastTextFrame(SwTextNode const * pNode, const sw::Creator& rCreator);
161 
162  bool bOldIdle;
163  static void DelSoftHyph( SwPaM &rPam );
164 
165 public:
166  SwHyphIter() : m_pLastNode(nullptr), m_pLastFrame(nullptr), bOldIdle(false) {}
167 
168  void Start( SwEditShell *pSh, SwDocPositions eStart, SwDocPositions eEnd );
169  void End();
170 
171  void Ignore();
172 
173  uno::Any Continue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt );
174 
175  static bool IsAuto();
176  void InsertSoftHyph( const sal_Int32 nHyphPos );
177  void ShowSelection();
178 };
179 
180 static SwSpellIter* g_pSpellIter = nullptr;
181 static SwConvIter* g_pConvIter = nullptr;
182 static SwHyphIter* g_pHyphIter = nullptr;
183 
185  : pSh(nullptr)
186  , nCursorCnt(0)
187 {
188  // TODO missing: ensurance of re-entrance, OSL_ENSURE( etc.
189 }
190 
192  SwDocPositions eEnd )
193 {
194  // TODO missing: ensurance of re-entrance, locking
195  if( pSh )
196  return;
197 
198  bool bSetCurr;
199 
200  pSh = pShell;
201 
202  SET_CURR_SHELL( pSh );
203 
204  OSL_ENSURE(!m_pEnd, "SwLinguIter::Start_ without End?");
205 
206  SwPaM *pCursor = pSh->GetCursor();
207 
208  if( pShell->HasSelection() || pCursor != pCursor->GetNext() )
209  {
210  bSetCurr = nullptr != GetCurr();
212  if( pSh->IsTableMode() )
214 
215  pSh->Push();
216  sal_uInt16 n;
217  for( n = 0; n < nCursorCnt; ++n )
218  {
219  pSh->Push();
220  pSh->DestroyCursor();
221  }
223  }
224  else
225  {
226  bSetCurr = false;
227  nCursorCnt = 1;
228  pSh->Push();
229  pSh->SetLinguRange( eStart, eEnd );
230  }
231 
232  pCursor = pSh->GetCursor();
233  if ( *pCursor->GetPoint() > *pCursor->GetMark() )
234  pCursor->Exchange();
235 
236  m_pStart.reset(new SwPosition(*pCursor->GetPoint()));
237  m_pEnd.reset(new SwPosition(*pCursor->GetMark()));
238  if( bSetCurr )
239  {
240  SwPosition* pNew = new SwPosition( *GetStart() );
241  SetCurr( pNew );
242  pNew = new SwPosition( *pNew );
243  SetCurrX( pNew );
244  }
245 
246  pCursor->SetMark();
247 }
248 
249 void SwLinguIter::End_(bool bRestoreSelection)
250 {
251  if( !pSh )
252  return;
253 
254  OSL_ENSURE(m_pEnd, "SwLinguIter::End_ without end?");
255  if(bRestoreSelection)
256  {
257  while( nCursorCnt-- )
259 
260  pSh->KillPams();
261  pSh->ClearMark();
262  }
263  m_pStart.reset();
264  m_pEnd.reset();
265  m_pCurr.reset();
266  m_pCurrX.reset();
267 
268  pSh = nullptr;
269 }
270 
272  SwDocPositions eEnd )
273 {
274  if( GetSh() )
275  return;
276 
278  if ( xSpeller.is() )
279  Start_( pShell, eStart, eEnd );
280  aLastPortions.clear();
281  aLastPositions.clear();
282 }
283 
284 // This method is the origin of SwEditShell::SpellContinue()
285 uno::Any SwSpellIter::Continue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
286 {
290 
291  uno::Any aSpellRet;
292  SwEditShell *pMySh = GetSh();
293  if( !pMySh )
294  return aSpellRet;
295 
296  OSL_ENSURE( GetEnd(), "SwSpellIter::Continue without start?");
297 
298  uno::Reference< uno::XInterface > xSpellRet;
299  bool bGoOn = true;
300  do {
301  SwPaM *pCursor = pMySh->GetCursor();
302  if ( !pCursor->HasMark() )
303  pCursor->SetMark();
304 
305  *pMySh->GetCursor()->GetPoint() = *GetCurr();
306  *pMySh->GetCursor()->GetMark() = *GetEnd();
307  pMySh->GetDoc()->Spell(*pMySh->GetCursor(),
308  xSpeller, pPageCnt, pPageSt, false, pMySh->GetLayout()) >>= xSpellRet;
309  bGoOn = GetCursorCnt() > 1;
310  if( xSpellRet.is() )
311  {
312  bGoOn = false;
313  SwPosition* pNewPoint = new SwPosition( *pCursor->GetPoint() );
314  SwPosition* pNewMark = new SwPosition( *pCursor->GetMark() );
315  SetCurr( pNewPoint );
316  SetCurrX( pNewMark );
317  }
318  if( bGoOn )
319  {
321  pCursor = pMySh->GetCursor();
322  if ( *pCursor->GetPoint() > *pCursor->GetMark() )
323  pCursor->Exchange();
324  SwPosition* pNew = new SwPosition( *pCursor->GetPoint() );
325  SetStart( pNew );
326  pNew = new SwPosition( *pCursor->GetMark() );
327  SetEnd( pNew );
328  pNew = new SwPosition( *GetStart() );
329  SetCurr( pNew );
330  pNew = new SwPosition( *pNew );
331  SetCurrX( pNew );
332  pCursor->SetMark();
333  --GetCursorCnt();
334  }
335  }while ( bGoOn );
336  aSpellRet <<= xSpellRet;
337  return aSpellRet;
338 }
339 
341  SwDocPositions eEnd )
342 {
343  if( GetSh() )
344  return;
345  Start_( pShell, eStart, eEnd );
346 }
347 
348 uno::Any SwConvIter::Continue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
349 {
353 
354  uno::Any aConvRet( makeAny( OUString() ) );
355  SwEditShell *pMySh = GetSh();
356  if( !pMySh )
357  return aConvRet;
358 
359  OSL_ENSURE( GetEnd(), "SwConvIter::Continue() without Start?");
360 
361  OUString aConvText;
362  bool bGoOn = true;
363  do {
364  SwPaM *pCursor = pMySh->GetCursor();
365  if ( !pCursor->HasMark() )
366  pCursor->SetMark();
367 
368  *pMySh->GetCursor()->GetPoint() = *GetCurr();
369  *pMySh->GetCursor()->GetMark() = *GetEnd();
370 
371  // call function to find next text portion to be converted
372  uno::Reference< linguistic2::XSpellChecker1 > xEmpty;
373  pMySh->GetDoc()->Spell( *pMySh->GetCursor(),
374  xEmpty, pPageCnt, pPageSt, false, pMySh->GetLayout(), &rArgs) >>= aConvText;
375 
376  bGoOn = GetCursorCnt() > 1;
377  if( !aConvText.isEmpty() )
378  {
379  bGoOn = false;
380  SwPosition* pNewPoint = new SwPosition( *pCursor->GetPoint() );
381  SwPosition* pNewMark = new SwPosition( *pCursor->GetMark() );
382 
383  SetCurr( pNewPoint );
384  SetCurrX( pNewMark );
385  }
386  if( bGoOn )
387  {
389  pCursor = pMySh->GetCursor();
390  if ( *pCursor->GetPoint() > *pCursor->GetMark() )
391  pCursor->Exchange();
392  SwPosition* pNew = new SwPosition( *pCursor->GetPoint() );
393  SetStart( pNew );
394  pNew = new SwPosition( *pCursor->GetMark() );
395  SetEnd( pNew );
396  pNew = new SwPosition( *GetStart() );
397  SetCurr( pNew );
398  pNew = new SwPosition( *pNew );
399  SetCurrX( pNew );
400  pCursor->SetMark();
401  --GetCursorCnt();
402  }
403  }while ( bGoOn );
404  return makeAny( aConvText );
405 }
406 
408 {
409  uno::Reference< beans::XPropertySet > xProp( ::GetLinguPropertySet() );
410  return xProp.is() && *o3tl::doAccess<bool>(xProp->getPropertyValue(
411  UPN_IS_HYPH_AUTO ));
412 }
413 
415 {
416  SwEditShell *pMySh = GetSh();
417  if( pMySh )
418  {
419  pMySh->StartAction();
420  // Caution! Due to EndAction() formatting is started which can lead to the fact that new
421  // words are added to/set in the Hyphenator. Thus: save!
422  pMySh->EndAction();
423  }
424 }
425 
427 {
428  // robust
429  if( GetSh() || GetEnd() )
430  {
431  OSL_ENSURE( !GetSh(), "SwHyphIter::Start: missing HyphEnd()" );
432  return;
433  }
434 
435  // nothing to do (at least not in the way as in the "else" part)
436  bOldIdle = pShell->GetViewOptions()->IsIdle();
437  pShell->GetViewOptions()->SetIdle( false );
438  Start_( pShell, eStart, eEnd );
439 }
440 
441 // restore selections
443 {
444  if( !GetSh() )
445  return;
447  End_();
448 }
449 
450 uno::Any SwHyphIter::Continue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
451 {
452  uno::Any aHyphRet;
453  SwEditShell *pMySh = GetSh();
454  if( !pMySh )
455  return aHyphRet;
456 
457  const bool bAuto = IsAuto();
458  uno::Reference< XHyphenatedWord > xHyphWord;
459  bool bGoOn = false;
460  do {
461  SwPaM *pCursor;
462  do {
463  OSL_ENSURE( GetEnd(), "SwHyphIter::Continue without Start?" );
464  pCursor = pMySh->GetCursor();
465  if ( !pCursor->HasMark() )
466  pCursor->SetMark();
467  if ( *pCursor->GetPoint() < *pCursor->GetMark() )
468  {
469  pCursor->Exchange();
470  pCursor->SetMark();
471  }
472 
473  if ( *pCursor->End() <= *GetEnd() )
474  {
475  *pCursor->GetMark() = *GetEnd();
476 
477  // Do we need to break the word at the current cursor position?
478  const Point aCursorPos( pMySh->GetCharRect().Pos() );
479  xHyphWord = pMySh->GetDoc()->Hyphenate( pCursor, aCursorPos,
480  pPageCnt, pPageSt );
481  }
482 
483  if( bAuto && xHyphWord.is() )
484  {
485  SwEditShell::InsertSoftHyph( xHyphWord->getHyphenationPos() + 1);
486  }
487  } while( bAuto && xHyphWord.is() ); //end of do-while
488  bGoOn = !xHyphWord.is() && GetCursorCnt() > 1;
489 
490  if( bGoOn )
491  {
493  pCursor = pMySh->GetCursor();
494  if ( *pCursor->GetPoint() > *pCursor->GetMark() )
495  pCursor->Exchange();
496  SwPosition* pNew = new SwPosition(*pCursor->End());
497  SetEnd( pNew );
498  pCursor->SetMark();
499  --GetCursorCnt();
500  }
501  } while ( bGoOn );
502  aHyphRet <<= xHyphWord;
503  return aHyphRet;
504 }
505 
508 {
509  SwEditShell *pMySh = GetSh();
510  SwPaM *pCursor = pMySh->GetCursor();
511 
512  // delete old SoftHyphen
513  DelSoftHyph( *pCursor );
514 
515  // and continue
516  pCursor->Start()->nContent = pCursor->End()->nContent;
517  pCursor->SetMark();
518 }
519 
521 {
522  const SwPosition* pStt = rPam.Start();
523  const sal_Int32 nStart = pStt->nContent.GetIndex();
524  const sal_Int32 nEnd = rPam.End()->nContent.GetIndex();
525  SwTextNode *pNode = pStt->nNode.GetNode().GetTextNode();
526  pNode->DelSoftHyph( nStart, nEnd );
527 }
528 
529 void SwHyphIter::InsertSoftHyph( const sal_Int32 nHyphPos )
530 {
531  SwEditShell *pMySh = GetSh();
532  OSL_ENSURE( pMySh, "SwHyphIter::InsertSoftHyph: missing HyphStart()");
533  if( !pMySh )
534  return;
535 
536  SwPaM *pCursor = pMySh->GetCursor();
537  SwPosition* pSttPos = pCursor->Start();
538  SwPosition* pEndPos = pCursor->End();
539 
540  const sal_Int32 nLastHyphLen = GetEnd()->nContent.GetIndex() -
541  pSttPos->nContent.GetIndex();
542 
543  if( pSttPos->nNode != pEndPos->nNode || !nLastHyphLen )
544  {
545  OSL_ENSURE( pSttPos->nNode == pEndPos->nNode,
546  "SwHyphIter::InsertSoftHyph: node warp during hyphenation" );
547  OSL_ENSURE(nLastHyphLen, "SwHyphIter::InsertSoftHyph: missing HyphContinue()");
548  *pSttPos = *pEndPos;
549  return;
550  }
551 
552  pMySh->StartAction();
553  {
554  SwDoc *pDoc = pMySh->GetDoc();
555  DelSoftHyph( *pCursor );
556  pSttPos->nContent += nHyphPos;
557  SwPaM aRg( *pSttPos );
559  }
560  // revoke selection
561  pCursor->DeleteMark();
562  pMySh->EndAction();
563  pCursor->SetMark();
564 }
565 
566 namespace sw {
567 
568 SwTextFrame *
570 {
571  assert(g_pHyphIter);
572  if (pNode != g_pHyphIter->m_pLastNode || !g_pHyphIter->m_pLastFrame)
573  {
574  g_pHyphIter->m_pLastNode = pNode;
575  g_pHyphIter->m_pLastFrame = create();
576  }
577  return g_pHyphIter->m_pLastFrame;
578 }
579 
580 }
581 
583 {
584  bool bTextWasGrammarChecked = false;
585  if (g_pSpellIter)
586  {
587  svx::SpellPortions aLastPortions( g_pSpellIter->GetLastPortions() );
588  for (size_t i = 0; i < aLastPortions.size() && !bTextWasGrammarChecked; ++i)
589  {
590  // bIsGrammarError is also true if the text was only checked but no
591  // grammar error was found. (That is if a ProofreadingResult was obtained in
592  // SwDoc::Spell and in turn bIsGrammarError was set in SwSpellIter::CreatePortion)
593  if (aLastPortions[i].bIsGrammarError)
594  bTextWasGrammarChecked = true;
595  }
596  }
597  return bTextWasGrammarChecked;
598 }
599 
601 {
602  return nullptr != g_pConvIter;
603 }
604 
606 {
607  return nullptr != g_pHyphIter;
608 }
609 
611 {
612  SwPaM *pCursor = GetCursor();
613  MakeFindRange( eStart, eEnd, pCursor );
614  if( *pCursor->GetPoint() > *pCursor->GetMark() )
615  pCursor->Exchange();
616 }
617 
619  SwDocPositions eStart, SwDocPositions eEnd, SwDocPositions eCurr,
620  SwConversionArgs *pConvArgs )
621 {
622  SwLinguIter *pLinguIter = nullptr;
623 
624  // do not spell if interactive spelling is active elsewhere
625  if (!pConvArgs && !g_pSpellIter)
626  {
627  g_pSpellIter = new SwSpellIter;
628  pLinguIter = g_pSpellIter;
629  }
630  // do not do text conversion if it is active elsewhere
631  if (pConvArgs && !g_pConvIter)
632  {
633  g_pConvIter = new SwConvIter( *pConvArgs );
634  pLinguIter = g_pConvIter;
635  }
636 
637  if (pLinguIter)
638  {
639  SwCursor* pSwCursor = GetSwCursor();
640 
641  SwPosition *pTmp = new SwPosition( *pSwCursor->GetPoint() );
642  pSwCursor->FillFindPos( eCurr, *pTmp );
643  pLinguIter->SetCurr( pTmp );
644 
645  pTmp = new SwPosition( *pTmp );
646  pLinguIter->SetCurrX( pTmp );
647  }
648 
649  if (!pConvArgs && g_pSpellIter)
650  g_pSpellIter->Start( this, eStart, eEnd );
651  if (pConvArgs && g_pConvIter)
652  g_pConvIter->Start( this, eStart, eEnd );
653 }
654 
655 void SwEditShell::SpellEnd( SwConversionArgs const *pConvArgs, bool bRestoreSelection )
656 {
657  if (!pConvArgs && g_pSpellIter && g_pSpellIter->GetSh() == this)
658  {
659  g_pSpellIter->End_(bRestoreSelection);
660  delete g_pSpellIter;
661  g_pSpellIter = nullptr;
662  }
663  if (pConvArgs && g_pConvIter && g_pConvIter->GetSh() == this)
664  {
665  g_pConvIter->End_();
666  delete g_pConvIter;
667  g_pConvIter = nullptr;
668  }
669 }
670 
673  sal_uInt16* pPageCnt, sal_uInt16* pPageSt,
674  SwConversionArgs const *pConvArgs )
675 {
676  uno::Any aRes;
677 
678  if ((!pConvArgs && g_pSpellIter->GetSh() != this) ||
679  ( pConvArgs && g_pConvIter->GetSh() != this))
680  return aRes;
681 
682  if( pPageCnt && !*pPageCnt )
683  {
684  sal_uInt16 nEndPage = GetLayout()->GetPageNum();
685  nEndPage += nEndPage * 10 / 100;
686  *pPageCnt = nEndPage;
687  if( nEndPage )
688  ::StartProgress( STR_STATSTR_SPELL, 0, nEndPage, GetDoc()->GetDocShell() );
689  }
690 
691  OSL_ENSURE( pConvArgs || g_pSpellIter, "SpellIter missing" );
692  OSL_ENSURE( !pConvArgs || g_pConvIter, "ConvIter missing" );
693  //JP 18.07.95: prevent displaying selection on error messages. NO StartAction so that all
694  // Paints are also disabled.
695  ++mnStartAction;
696  OUString aRet;
697  uno::Reference< uno::XInterface > xRet;
698  if (pConvArgs)
699  {
700  g_pConvIter->Continue( pPageCnt, pPageSt ) >>= aRet;
701  aRes <<= aRet;
702  }
703  else
704  {
705  g_pSpellIter->Continue( pPageCnt, pPageSt ) >>= xRet;
706  aRes <<= xRet;
707  }
708  --mnStartAction;
709 
710  if( !aRet.isEmpty() || xRet.is() )
711  {
712  // then make awt::Selection again visible
713  StartAction();
714  EndAction();
715  }
716  return aRes;
717 }
718 
719 /* Interactive Hyphenation (BP 10.03.93)
720  *
721  * 1) HyphStart
722  * - Revoke all Selections
723  * - Save current Cursor
724  * - if no selections existent:
725  * - create new selection reaching until document end
726  * 2) HyphContinue
727  * - add nLastHyphLen onto SelectionStart
728  * - iterate over all selected areas
729  * - pDoc->Hyphenate() iterates over all Nodes of a selection
730  * - pTextNode->Hyphenate() calls SwTextFrame::Hyphenate of the EditShell
731  * - SwTextFrame:Hyphenate() iterates over all rows of the Pam
732  * - LineIter::Hyphenate() sets the Hyphenator and the Pam based on
733  * the to be separated word.
734  * - Returns true if there is a hyphenation and false if the Pam is processed.
735  * - If true, show the selected word and set nLastHyphLen.
736  * - If false, delete current selection and select next one. Returns HYPH_OK if no more.
737  * 3) InsertSoftHyph (might be called by UI if needed)
738  * - Place current cursor and add attribute.
739  * 4) HyphEnd
740  * - Restore old cursor, EndAction
741  */
743 {
744  // do not hyphenate if interactive hyphenation is active elsewhere
745  if (!g_pHyphIter)
746  {
747  g_pHyphIter = new SwHyphIter;
748  g_pHyphIter->Start( this, eStart, eEnd );
749  }
750 }
751 
754 {
755  assert(g_pHyphIter);
756  if (g_pHyphIter->GetSh() == this)
757  {
758  g_pHyphIter->End();
759  delete g_pHyphIter;
760  g_pHyphIter = nullptr;
761  }
762 }
763 
765 uno::Reference< uno::XInterface >
766  SwEditShell::HyphContinue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
767 {
768  assert(g_pHyphIter);
769  if (g_pHyphIter->GetSh() != this)
770  return nullptr;
771 
772  if( pPageCnt && !*pPageCnt && !*pPageSt )
773  {
774  sal_uInt16 nEndPage = GetLayout()->GetPageNum();
775  nEndPage += nEndPage * 10 / 100;
776  if( nEndPage > 14 )
777  {
778  *pPageCnt = nEndPage;
779  ::StartProgress( STR_STATSTR_HYPHEN, 0, nEndPage, GetDoc()->GetDocShell());
780  }
781  else // here we once and for all suppress StatLineStartPercent
782  *pPageSt = 1;
783  }
784 
785  //JP 18.07.95: prevent displaying selection on error messages. NO StartAction so that all
786  // Paints are also disabled.
787  ++mnStartAction;
788  uno::Reference< uno::XInterface > xRet;
789  g_pHyphIter->Continue( pPageCnt, pPageSt ) >>= xRet;
790  --mnStartAction;
791 
792  if( xRet.is() )
793  g_pHyphIter->ShowSelection();
794 
795  return xRet;
796 }
797 
802 void SwEditShell::InsertSoftHyph( const sal_Int32 nHyphPos )
803 {
804  assert(g_pHyphIter);
805  g_pHyphIter->InsertSoftHyph( nHyphPos );
806 }
807 
810 {
811  assert(g_pHyphIter);
812  //JP 18.07.95: prevent displaying selection on error messages. NO StartAction so that all
813  // Paints are also disabled.
814  ++mnStartAction;
815  g_pHyphIter->Ignore();
816  --mnStartAction;
817 
818  g_pHyphIter->ShowSelection();
819 }
820 
821 void SwEditShell::HandleCorrectionError(const OUString& aText, SwPosition aPos, sal_Int32 nBegin,
822  sal_Int32 nLen, const Point* pPt,
823  SwRect& rSelectRect)
824 {
825  // save the start and end positions of the line and the starting point
826  Push();
827  LeftMargin();
828  const sal_Int32 nLineStart = GetCursor()->GetPoint()->nContent.GetIndex();
829  RightMargin();
830  const sal_Int32 nLineEnd = GetCursor()->GetPoint()->nContent.GetIndex();
832 
833  // make sure the selection build later from the data below does
834  // not "in word" character to the left and right in order to
835  // preserve those. Therefore count those "in words" in order to
836  // modify the selection accordingly.
837  const sal_Unicode* pChar = aText.getStr();
838  sal_Int32 nLeft = 0;
839  while (*pChar++ == CH_TXTATR_INWORD)
840  ++nLeft;
841  pChar = aText.getLength() ? aText.getStr() + aText.getLength() - 1 : nullptr;
842  sal_Int32 nRight = 0;
843  while (pChar && *pChar-- == CH_TXTATR_INWORD)
844  ++nRight;
845 
846  aPos.nContent = nBegin + nLeft;
847  SwPaM* pCursor = GetCursor();
848  *pCursor->GetPoint() = aPos;
849  pCursor->SetMark();
850  ExtendSelection( true, nLen - nLeft - nRight );
851  // don't determine the rectangle in the current line
852  const sal_Int32 nWordStart = (nBegin + nLeft) < nLineStart ? nLineStart : nBegin + nLeft;
853  // take one less than the line end - otherwise the next line would be calculated
854  const sal_Int32 nWordEnd = (nBegin + nLen - nLeft - nRight) > nLineEnd
855  ? nLineEnd : (nBegin + nLen - nLeft - nRight);
856  Push();
857  pCursor->DeleteMark();
858  SwIndex& rContent = GetCursor()->GetPoint()->nContent;
859  rContent = nWordStart;
860  SwRect aStartRect;
861  SwCursorMoveState aState;
862  aState.m_bRealWidth = true;
863  SwContentNode* pContentNode = pCursor->GetContentNode();
864  std::pair<Point, bool> tmp;
865  if (pPt)
866  {
867  tmp.first = *pPt;
868  tmp.second = false;
869  }
870  SwContentFrame *const pContentFrame = pContentNode->getLayoutFrame(GetLayout(), pCursor->GetPoint(), pPt ? &tmp : nullptr);
871 
872  pContentFrame->GetCharRect( aStartRect, *pCursor->GetPoint(), &aState );
873  rContent = nWordEnd - 1;
874  SwRect aEndRect;
875  pContentFrame->GetCharRect( aEndRect, *pCursor->GetPoint(),&aState );
876  rSelectRect = aStartRect.Union( aEndRect );
878 }
879 
888 uno::Reference< XSpellAlternatives >
889  SwEditShell::GetCorrection( const Point* pPt, SwRect& rSelectRect )
890 {
891  uno::Reference< XSpellAlternatives > xSpellAlt;
892 
893  if( IsTableMode() )
894  return nullptr;
895  SwPaM* pCursor = GetCursor();
896  SwPosition aPos( *pCursor->GetPoint() );
897  Point aPt( *pPt );
898  SwCursorMoveState eTmpState( MV_SETONLYTEXT );
899  SwTextNode *pNode = nullptr;
900  SwWrongList *pWrong = nullptr;
901  if (GetLayout()->GetCursorOfst( &aPos, aPt, &eTmpState ))
902  pNode = aPos.nNode.GetNode().GetTextNode();
903  if (nullptr != pNode)
904  pWrong = pNode->GetWrong();
905  if (nullptr != pWrong && !pNode->IsInProtectSect())
906  {
907  sal_Int32 nBegin = aPos.nContent.GetIndex();
908  sal_Int32 nLen = 1;
909  if (pWrong->InWrongWord(nBegin, nLen) && !pNode->IsSymbolAt(nBegin))
910  {
911  const OUString aText(pNode->GetText().copy(nBegin, nLen));
912  OUString aWord = aText.replaceAll(OUStringLiteral1(CH_TXTATR_BREAKWORD), "")
913  .replaceAll(OUStringLiteral1(CH_TXTATR_INWORD), "");
914 
915  uno::Reference< XSpellChecker1 > xSpell( ::GetSpellChecker() );
916  if( xSpell.is() )
917  {
918  LanguageType eActLang = pNode->GetLang( nBegin, nLen );
919  if( xSpell->hasLanguage( static_cast<sal_uInt16>(eActLang) ))
920  {
921  // restrict the maximal number of suggestions displayed
922  // in the context menu.
923  // Note: That could of course be done by clipping the
924  // resulting sequence but the current third party
925  // implementations result differs greatly if the number of
926  // suggestions to be returned gets changed. Statistically
927  // it gets much better if told to return e.g. only 7 strings
928  // than returning e.g. 16 suggestions and using only the
929  // first 7. Thus we hand down the value to use to that
930  // implementation here by providing an additional parameter.
931  Sequence< PropertyValue > aPropVals(1);
932  PropertyValue &rVal = aPropVals.getArray()[0];
933  rVal.Name = UPN_MAX_NUMBER_OF_SUGGESTIONS;
934  rVal.Value <<= sal_Int16(7);
935 
936  xSpellAlt = xSpell->spell( aWord, static_cast<sal_uInt16>(eActLang), aPropVals );
937  }
938  }
939 
940  if ( xSpellAlt.is() ) // error found?
941  {
942  HandleCorrectionError( aText, aPos, nBegin, nLen, pPt, rSelectRect );
943  }
944  }
945  }
946  return xSpellAlt;
947 }
948 
950  linguistic2::ProofreadingResult /*out*/ &rResult, // the complete result
951  sal_Int32 /*out*/ &rErrorPosInText, // offset of error position in string that was grammar checked...
952  sal_Int32 /*out*/ &rErrorIndexInResult, // index of error in rResult.aGrammarErrors
953  uno::Sequence< OUString > /*out*/ &rSuggestions, // suggestions to be used for the error found
954  const Point *pPt, SwRect &rSelectRect )
955 {
956  bool bRes = false;
957 
958  if( IsTableMode() )
959  return bRes;
960 
961  SwPaM* pCursor = GetCursor();
962  SwPosition aPos( *pCursor->GetPoint() );
963  Point aPt( *pPt );
964  SwCursorMoveState eTmpState( MV_SETONLYTEXT );
965  SwTextNode *pNode = nullptr;
966  SwGrammarMarkUp *pWrong = nullptr;
967  if (GetLayout()->GetCursorOfst( &aPos, aPt, &eTmpState ))
968  pNode = aPos.nNode.GetNode().GetTextNode();
969  if (nullptr != pNode)
970  pWrong = pNode->GetGrammarCheck();
971  if (nullptr != pWrong && !pNode->IsInProtectSect())
972  {
973  sal_Int32 nBegin = aPos.nContent.GetIndex();
974  sal_Int32 nLen = 1;
975  if (pWrong->InWrongWord(nBegin, nLen))
976  {
977  const OUString aText(pNode->GetText().copy(nBegin, nLen));
978 
979  uno::Reference< linguistic2::XProofreadingIterator > xGCIterator( mxDoc->GetGCIterator() );
980  if (xGCIterator.is())
981  {
982  uno::Reference< lang::XComponent > xDoc( mxDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY );
983 
984  // Expand the string:
985  const ModelToViewHelper aConversionMap(*pNode, GetLayout());
986  const OUString& aExpandText = aConversionMap.getViewText();
987  // get XFlatParagraph to use...
988  uno::Reference< text::XFlatParagraph > xFlatPara = new SwXFlatParagraph( *pNode, aExpandText, aConversionMap );
989 
990  // get error position of cursor in XFlatParagraph
991  rErrorPosInText = aConversionMap.ConvertToViewPosition( nBegin );
992 
993  const sal_Int32 nStartOfSentence = aConversionMap.ConvertToViewPosition( pWrong->getSentenceStart( nBegin ) );
994  const sal_Int32 nEndOfSentence = aConversionMap.ConvertToViewPosition( pWrong->getSentenceEnd( nBegin ) );
995 
996  rResult = xGCIterator->checkSentenceAtPosition(
997  xDoc, xFlatPara, aExpandText, lang::Locale(), nStartOfSentence,
998  nEndOfSentence == COMPLETE_STRING ? aExpandText.getLength() : nEndOfSentence,
999  rErrorPosInText );
1000  bRes = true;
1001 
1002  // get suggestions to use for the specific error position
1003  sal_Int32 nErrors = rResult.aErrors.getLength();
1004  rSuggestions.realloc( 0 );
1005  for (sal_Int32 i = 0; i < nErrors; ++i )
1006  {
1007  // return suggestions for first error that includes the given error position
1008  const linguistic2::SingleProofreadingError &rError = rResult.aErrors[i];
1009  if (rError.nErrorStart <= rErrorPosInText &&
1010  rErrorPosInText + nLen <= rError.nErrorStart + rError.nErrorLength)
1011  {
1012  rSuggestions = rError.aSuggestions;
1013  rErrorIndexInResult = i;
1014  break;
1015  }
1016  }
1017  }
1018 
1019  if (rResult.aErrors.hasElements()) // error found?
1020  {
1021  HandleCorrectionError( aText, aPos, nBegin, nLen, pPt, rSelectRect );
1022  }
1023  }
1024  }
1025 
1026  return bRes;
1027 }
1028 
1029 bool SwEditShell::SpellSentence(svx::SpellPortions& rPortions, bool bIsGrammarCheck)
1030 {
1031  OSL_ENSURE( g_pSpellIter, "SpellIter missing" );
1032  if (!g_pSpellIter)
1033  return false;
1034  bool bRet = g_pSpellIter->SpellSentence(rPortions, bIsGrammarCheck);
1035 
1036  // make Selection visible - this should simply move the
1037  // cursor to the end of the sentence
1038  StartAction();
1039  EndAction();
1040  return bRet;
1041 }
1042 
1045 {
1046  OSL_ENSURE( g_pSpellIter, "SpellIter missing" );
1047  if (!g_pSpellIter)
1048  return;
1049  g_pSpellIter->ToSentenceStart();
1050 }
1051 
1052 static sal_uInt32 lcl_CountRedlines(const svx::SpellPortions& rLastPortions)
1053 {
1054  return static_cast<sal_uInt32>(std::count_if(rLastPortions.begin(), rLastPortions.end(),
1055  [](const svx::SpellPortion& rPortion) { return rPortion.bIsHidden; }));
1056 }
1057 
1059 {
1060  // give hint that continuation position for spell/grammar checking is
1061  // at the end of this sentence
1062  if (g_pSpellIter)
1063  {
1064  g_pSpellIter->SetCurr( new SwPosition( *g_pSpellIter->GetCurrX() ) );
1065  }
1066 }
1067 
1068 void SwEditShell::ApplyChangedSentence(const svx::SpellPortions& rNewPortions, bool bRecheck)
1069 {
1070  // Note: rNewPortions.size() == 0 is valid and happens when the whole
1071  // sentence got removed in the dialog
1072 
1073  OSL_ENSURE( g_pSpellIter, "SpellIter missing" );
1074  if (!g_pSpellIter ||
1075  g_pSpellIter->GetLastPortions().empty()) // no portions -> no text to be changed
1076  return;
1077 
1078  const SpellPortions& rLastPortions = g_pSpellIter->GetLastPortions();
1079  const SpellContentPositions rLastPositions = g_pSpellIter->GetLastPositions();
1080  OSL_ENSURE(!rLastPortions.empty() &&
1081  rLastPortions.size() == rLastPositions.size(),
1082  "last vectors of spelling results are not set or not equal");
1083 
1084  // iterate over the new portions, beginning at the end to take advantage of the previously
1085  // saved content positions
1086 
1087  mxDoc->GetIDocumentUndoRedo().StartUndo( SwUndoId::UI_TEXT_CORRECTION, nullptr );
1088  StartAction();
1089 
1090  SwPaM *pCursor = GetCursor();
1091  // save cursor position (which should be at the end of the current sentence)
1092  // for later restoration
1093  Push();
1094 
1095  sal_uInt32 nRedlinePortions = lcl_CountRedlines(rLastPortions);
1096  if((rLastPortions.size() - nRedlinePortions) == rNewPortions.size())
1097  {
1098  OSL_ENSURE( !rNewPortions.empty(), "rNewPortions should not be empty here" );
1099  OSL_ENSURE( !rLastPortions.empty(), "rLastPortions should not be empty here" );
1100  OSL_ENSURE( !rLastPositions.empty(), "rLastPositions should not be empty here" );
1101 
1102  // the simple case: the same number of elements on both sides
1103  // each changed element has to be applied to the corresponding source element
1104  svx::SpellPortions::const_iterator aCurrentNewPortion = rNewPortions.end();
1105  SpellPortions::const_iterator aCurrentOldPortion = rLastPortions.end();
1106  SpellContentPositions::const_iterator aCurrentOldPosition = rLastPositions.end();
1107  do
1108  {
1109  --aCurrentNewPortion;
1110  --aCurrentOldPortion;
1111  --aCurrentOldPosition;
1112  //jump over redline portions
1113  while(aCurrentOldPortion->bIsHidden)
1114  {
1115  if (aCurrentOldPortion != rLastPortions.begin() &&
1116  aCurrentOldPosition != rLastPositions.begin())
1117  {
1118  --aCurrentOldPortion;
1119  --aCurrentOldPosition;
1120  }
1121  else
1122  {
1123  OSL_FAIL("ApplyChangedSentence: iterator positions broken" );
1124  break;
1125  }
1126  }
1127  if ( !pCursor->HasMark() )
1128  pCursor->SetMark();
1129  pCursor->GetPoint()->nContent = aCurrentOldPosition->nLeft;
1130  pCursor->GetMark()->nContent = aCurrentOldPosition->nRight;
1131  sal_uInt16 nScriptType = SvtLanguageOptions::GetI18NScriptTypeOfLanguage( aCurrentNewPortion->eLanguage );
1132  sal_uInt16 nLangWhichId = RES_CHRATR_LANGUAGE;
1133  switch(nScriptType)
1134  {
1135  case css::i18n::ScriptType::ASIAN : nLangWhichId = RES_CHRATR_CJK_LANGUAGE; break;
1136  case css::i18n::ScriptType::COMPLEX : nLangWhichId = RES_CHRATR_CTL_LANGUAGE; break;
1137  }
1138  if(aCurrentNewPortion->sText != aCurrentOldPortion->sText)
1139  {
1140  // change text ...
1141  mxDoc->getIDocumentContentOperations().DeleteAndJoin(*pCursor);
1142  // ... and apply language if necessary
1143  if(aCurrentNewPortion->eLanguage != aCurrentOldPortion->eLanguage)
1144  SetAttrItem( SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId) );
1145  mxDoc->getIDocumentContentOperations().InsertString(*pCursor, aCurrentNewPortion->sText);
1146  }
1147  else if(aCurrentNewPortion->eLanguage != aCurrentOldPortion->eLanguage)
1148  {
1149  // apply language
1150  SetAttrItem( SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId) );
1151  }
1152  else if( aCurrentNewPortion->bIgnoreThisError )
1153  {
1154  // add the 'ignore' markup to the TextNode's grammar ignore markup list
1155  IgnoreGrammarErrorAt( *pCursor );
1156  OSL_FAIL("TODO: add ignore mark to text node");
1157  }
1158  }
1159  while(aCurrentNewPortion != rNewPortions.begin());
1160  }
1161  else
1162  {
1163  OSL_ENSURE( !rLastPositions.empty(), "rLastPositions should not be empty here" );
1164 
1165  // select the complete sentence
1166  SpellContentPositions::const_iterator aCurrentEndPosition = rLastPositions.end();
1167  --aCurrentEndPosition;
1168  SpellContentPositions::const_iterator aCurrentStartPosition = rLastPositions.begin();
1169  pCursor->GetPoint()->nContent = aCurrentStartPosition->nLeft;
1170  pCursor->GetMark()->nContent = aCurrentEndPosition->nRight;
1171 
1172  // delete the sentence completely
1173  mxDoc->getIDocumentContentOperations().DeleteAndJoin(*pCursor);
1174  for(const auto& rCurrentNewPortion : rNewPortions)
1175  {
1176  // set the language attribute
1177  SvtScriptType nScriptType = GetScriptType();
1178  sal_uInt16 nLangWhichId = RES_CHRATR_LANGUAGE;
1179  switch(nScriptType)
1180  {
1181  case SvtScriptType::ASIAN : nLangWhichId = RES_CHRATR_CJK_LANGUAGE; break;
1182  case SvtScriptType::COMPLEX : nLangWhichId = RES_CHRATR_CTL_LANGUAGE; break;
1183  default: break;
1184  }
1185  SfxItemSet aSet(GetAttrPool(), {{nLangWhichId, nLangWhichId}});
1186  GetCurAttr( aSet );
1187  const SvxLanguageItem& rLang = static_cast<const SvxLanguageItem& >(aSet.Get(nLangWhichId));
1188  if(rLang.GetLanguage() != rCurrentNewPortion.eLanguage)
1189  SetAttrItem( SvxLanguageItem(rCurrentNewPortion.eLanguage, nLangWhichId) );
1190  // insert the new string
1191  mxDoc->getIDocumentContentOperations().InsertString(*pCursor, rCurrentNewPortion.sText);
1192 
1193  // set the cursor to the end of the inserted string
1194  *pCursor->Start() = *pCursor->End();
1195  }
1196  }
1197 
1198  // restore cursor to the end of the sentence
1199  // (will work also if the sentence length has changed,
1200  // since cursors get updated automatically!)
1202 
1203  // collapse cursor to the end of the modified sentence
1204  *pCursor->Start() = *pCursor->End();
1205  if (bRecheck)
1206  {
1207  // in grammar check the current sentence has to be checked again
1208  GoStartSentence();
1209  }
1210  // set continuation position for spell/grammar checking to the end of this sentence
1211  g_pSpellIter->SetCurr( new SwPosition(*pCursor->Start()) );
1212 
1213  mxDoc->GetIDocumentUndoRedo().EndUndo( SwUndoId::UI_TEXT_CORRECTION, nullptr );
1214  EndAction();
1215 
1216 }
1221 {
1222  SpellContentPositions aRedlines;
1223  SwDoc* pDoc = pSh->GetDoc();
1225  if ( bShowChg )
1226  {
1227  SwPaM *pCursor = pSh->GetCursor();
1228  const SwPosition* pStartPos = pCursor->Start();
1229  const SwTextNode* pTextNode = pCursor->GetNode().GetTextNode();
1230 
1232  const sal_Int32 nStartIndex = pStartPos->nContent.GetIndex();
1233  for ( ; nAct < pDoc->getIDocumentRedlineAccess().GetRedlineTable().size(); nAct++ )
1234  {
1235  const SwRangeRedline* pRed = pDoc->getIDocumentRedlineAccess().GetRedlineTable()[ nAct ];
1236 
1237  if ( pRed->Start()->nNode > pTextNode->GetIndex() )
1238  break;
1239 
1240  if( RedlineType::Delete == pRed->GetType() )
1241  {
1242  sal_Int32 nStart_, nEnd_;
1243  pRed->CalcStartEnd( pTextNode->GetIndex(), nStart_, nEnd_ );
1244  sal_Int32 nStart = nStart_;
1245  sal_Int32 nEnd = nEnd_;
1246  if(nStart >= nStartIndex || nEnd >= nStartIndex)
1247  {
1248  SpellContentPosition aAdd;
1249  aAdd.nLeft = nStart;
1250  aAdd.nRight = nEnd;
1251  aRedlines.push_back(aAdd);
1252  }
1253  }
1254  }
1255  }
1256  return aRedlines;
1257 }
1258 
1260 static void lcl_CutRedlines( SpellContentPositions& aDeletedRedlines, SwEditShell const * pSh )
1261 {
1262  if(!aDeletedRedlines.empty())
1263  {
1264  SwPaM *pCursor = pSh->GetCursor();
1265  const SwPosition* pEndPos = pCursor->End();
1266  const sal_Int32 nEnd = pEndPos->nContent.GetIndex();
1267  while(!aDeletedRedlines.empty() &&
1268  aDeletedRedlines.back().nLeft > nEnd)
1269  {
1270  aDeletedRedlines.pop_back();
1271  }
1272  }
1273 }
1274 
1276  const SpellContentPositions& rDeletedRedlines,
1277  sal_Int32 nSearchFrom )
1278 {
1279  SpellContentPosition aRet;
1280  aRet.nLeft = aRet.nRight = SAL_MAX_INT32;
1281  if(!rDeletedRedlines.empty())
1282  {
1283  auto aIter = std::find_if_not(rDeletedRedlines.begin(), rDeletedRedlines.end(),
1284  [nSearchFrom](const SpellContentPosition& rPos) { return rPos.nLeft < nSearchFrom; });
1285  if (aIter != rDeletedRedlines.end())
1286  aRet = *aIter;
1287  }
1288  return aRet;
1289 }
1290 
1291 bool SwSpellIter::SpellSentence(svx::SpellPortions& rPortions, bool bIsGrammarCheck)
1292 {
1293  bool bRet = false;
1294  aLastPortions.clear();
1295  aLastPositions.clear();
1296 
1297  SwEditShell *pMySh = GetSh();
1298  if( !pMySh )
1299  return false;
1300 
1301  OSL_ENSURE( GetEnd(), "SwSpellIter::SpellSentence without Start?");
1302 
1303  uno::Reference< XSpellAlternatives > xSpellRet;
1304  linguistic2::ProofreadingResult aGrammarResult;
1305  bool bGoOn = true;
1306  bool bGrammarErrorFound = false;
1307  do {
1308  SwPaM *pCursor = pMySh->GetCursor();
1309  if ( !pCursor->HasMark() )
1310  pCursor->SetMark();
1311 
1312  *pCursor->GetPoint() = *GetCurr();
1313  *pCursor->GetMark() = *GetEnd();
1314 
1316  {
1317  pMySh->GoStartSentence();
1318  bBackToStartOfSentence = false;
1319  }
1320  uno::Any aSpellRet =
1321  pMySh->GetDoc()->Spell(*pCursor,
1322  xSpeller, nullptr, nullptr, bIsGrammarCheck, pMySh->GetLayout());
1323  aSpellRet >>= xSpellRet;
1324  aSpellRet >>= aGrammarResult;
1325  bGoOn = GetCursorCnt() > 1;
1326  bGrammarErrorFound = aGrammarResult.aErrors.hasElements();
1327  if( xSpellRet.is() || bGrammarErrorFound )
1328  {
1329  bGoOn = false;
1330  SwPosition* pNewPoint = new SwPosition( *pCursor->GetPoint() );
1331  SwPosition* pNewMark = new SwPosition( *pCursor->GetMark() );
1332 
1333  SetCurr( pNewPoint );
1334  SetCurrX( pNewMark );
1335  }
1336  if( bGoOn )
1337  {
1339  pCursor = pMySh->GetCursor();
1340  if ( *pCursor->GetPoint() > *pCursor->GetMark() )
1341  pCursor->Exchange();
1342  SwPosition* pNew = new SwPosition( *pCursor->GetPoint() );
1343  SetStart( pNew );
1344  pNew = new SwPosition( *pCursor->GetMark() );
1345  SetEnd( pNew );
1346  pNew = new SwPosition( *GetStart() );
1347  SetCurr( pNew );
1348  pNew = new SwPosition( *pNew );
1349  SetCurrX( pNew );
1350  pCursor->SetMark();
1351  --GetCursorCnt();
1352  }
1353  } while ( bGoOn );
1354 
1355  if(xSpellRet.is() || bGrammarErrorFound)
1356  {
1357  // an error has been found
1358  // To fill the spell portions the beginning of the sentence has to be found
1359  SwPaM *pCursor = pMySh->GetCursor();
1360  // set the mark to the right if necessary
1361  if ( *pCursor->GetPoint() > *pCursor->GetMark() )
1362  pCursor->Exchange();
1363  // the cursor has to be collapsed on the left to go to the start of the sentence - if sentence ends inside of the error
1364  pCursor->DeleteMark();
1365  pCursor->SetMark();
1366  bool bStartSent = pMySh->GoStartSentence();
1367  SpellContentPositions aDeletedRedlines = lcl_CollectDeletedRedlines(pMySh);
1368  if(bStartSent)
1369  {
1370  // create a portion from the start part
1371  AddPortion(nullptr, nullptr, aDeletedRedlines);
1372  }
1373  // Set the cursor to the error already found
1374  *pCursor->GetPoint() = *GetCurrX();
1375  *pCursor->GetMark() = *GetCurr();
1376  AddPortion(xSpellRet, &aGrammarResult, aDeletedRedlines);
1377 
1378  // save the end position of the error to continue from here
1379  SwPosition aSaveStartPos = *pCursor->End();
1380  // determine the end of the current sentence
1381  if ( *pCursor->GetPoint() < *pCursor->GetMark() )
1382  pCursor->Exchange();
1383  // again collapse to start marking after the end of the error
1384  pCursor->DeleteMark();
1385  pCursor->SetMark();
1386 
1387  pMySh->GoEndSentence();
1388  if( bGrammarErrorFound )
1389  {
1390  const ModelToViewHelper aConversionMap(static_cast<SwTextNode&>(pCursor->GetNode()), pMySh->GetLayout());
1391  const OUString& aExpandText = aConversionMap.getViewText();
1392  sal_Int32 nSentenceEnd =
1393  aConversionMap.ConvertToViewPosition( aGrammarResult.nBehindEndOfSentencePosition );
1394  // remove trailing space
1395  if( aExpandText[nSentenceEnd - 1] == ' ' )
1396  --nSentenceEnd;
1397  if( pCursor->End()->nContent.GetIndex() < nSentenceEnd )
1398  {
1399  pCursor->End()->nContent.Assign(
1400  pCursor->End()->nNode.GetNode().GetContentNode(), nSentenceEnd);
1401  }
1402  }
1403 
1404  lcl_CutRedlines( aDeletedRedlines, pMySh );
1405  // save the 'global' end of the spellchecking
1406  const SwPosition aSaveEndPos = *GetEnd();
1407  // set the sentence end as 'local' end
1408  SetEnd( new SwPosition( *pCursor->End() ));
1409 
1410  *pCursor->GetPoint() = aSaveStartPos;
1411  *pCursor->GetMark() = *GetEnd();
1412  // now the rest of the sentence has to be searched for errors
1413  // for each error the non-error text between the current and the last error has
1414  // to be added to the portions - if necessary broken into same-language-portions
1415  if( !bGrammarErrorFound ) //in grammar check there's only one error returned
1416  {
1417  do
1418  {
1419  xSpellRet = nullptr;
1420  // don't search for grammar errors here anymore!
1421  pMySh->GetDoc()->Spell(*pCursor,
1422  xSpeller, nullptr, nullptr, false, pMySh->GetLayout()) >>= xSpellRet;
1423  if ( *pCursor->GetPoint() > *pCursor->GetMark() )
1424  pCursor->Exchange();
1425  SetCurr( new SwPosition( *pCursor->GetPoint() ));
1426  SetCurrX( new SwPosition( *pCursor->GetMark() ));
1427 
1428  // if an error has been found go back to the text preceding the error
1429  if(xSpellRet.is())
1430  {
1431  *pCursor->GetPoint() = aSaveStartPos;
1432  *pCursor->GetMark() = *GetCurr();
1433  }
1434  // add the portion
1435  AddPortion(nullptr, nullptr, aDeletedRedlines);
1436 
1437  if(xSpellRet.is())
1438  {
1439  *pCursor->GetPoint() = *GetCurr();
1440  *pCursor->GetMark() = *GetCurrX();
1441  AddPortion(xSpellRet, nullptr, aDeletedRedlines);
1442  // move the cursor to the end of the error string
1443  *pCursor->GetPoint() = *GetCurrX();
1444  // and save the end of the error as new start position
1445  aSaveStartPos = *GetCurrX();
1446  // and the end of the sentence
1447  *pCursor->GetMark() = *GetEnd();
1448  }
1449  // if the end of the sentence has already been reached then break here
1450  if(*GetCurrX() >= *GetEnd())
1451  break;
1452  }
1453  while(xSpellRet.is());
1454  }
1455  else
1456  {
1457  // go to the end of sentence as the grammar check returned it
1458  // at this time the Point is behind the grammar error
1459  // and the mark points to the sentence end as
1460  if ( *pCursor->GetPoint() < *pCursor->GetMark() )
1461  pCursor->Exchange();
1462  }
1463 
1464  // the part between the last error and the end of the sentence has to be added
1465  *pMySh->GetCursor()->GetPoint() = *GetEnd();
1466  if(*GetCurrX() < *GetEnd())
1467  {
1468  AddPortion(nullptr, nullptr, aDeletedRedlines);
1469  }
1470  // set the shell cursor to the end of the sentence to prevent a visible selection
1471  *pCursor->GetMark() = *GetEnd();
1472  if( !bIsGrammarCheck )
1473  {
1474  // set the current position to the end of the sentence
1475  SetCurr( new SwPosition(*GetEnd()) );
1476  }
1477  // restore the 'global' end
1478  SetEnd( new SwPosition(aSaveEndPos) );
1479  rPortions = aLastPortions;
1480  bRet = true;
1481  }
1482  else
1483  {
1484  // if no error could be found the selection has to be corrected - at least if it's not in the body
1485  *pMySh->GetCursor()->GetPoint() = *GetEnd();
1486  pMySh->GetCursor()->DeleteMark();
1487  }
1488 
1489  return bRet;
1490 }
1491 
1493 {
1494  bBackToStartOfSentence = true;
1495 }
1496 
1498 {
1499  SvtScriptType nScriptType = rSh.GetScriptType();
1500  sal_uInt16 nLangWhichId = RES_CHRATR_LANGUAGE;
1501 
1502  switch(nScriptType)
1503  {
1504  case SvtScriptType::ASIAN : nLangWhichId = RES_CHRATR_CJK_LANGUAGE; break;
1505  case SvtScriptType::COMPLEX : nLangWhichId = RES_CHRATR_CTL_LANGUAGE; break;
1506  default: break;
1507  }
1508  SfxItemSet aSet(rSh.GetAttrPool(), {{nLangWhichId, nLangWhichId}});
1509  rSh.GetCurAttr( aSet );
1510  const SvxLanguageItem& rLang = static_cast<const SvxLanguageItem& >(aSet.Get(nLangWhichId));
1511  return rLang.GetLanguage();
1512 }
1513 
1515 void SwSpellIter::CreatePortion(uno::Reference< XSpellAlternatives > const & xAlt,
1516  linguistic2::ProofreadingResult* pGrammarResult,
1517  bool bIsField, bool bIsHidden)
1518 {
1519  svx::SpellPortion aPortion;
1520  OUString sText;
1521  GetSh()->GetSelectedText( sText );
1522  if(sText.isEmpty())
1523  return;
1524 
1525  // in case of redlined deletions the selection of an error is not the same as the _real_ word
1526  if(xAlt.is())
1527  aPortion.sText = xAlt->getWord();
1528  else if(pGrammarResult)
1529  {
1530  aPortion.bIsGrammarError = true;
1531  if(pGrammarResult->aErrors.hasElements())
1532  {
1533  aPortion.aGrammarError = pGrammarResult->aErrors[0];
1534  aPortion.sText = pGrammarResult->aText.copy( aPortion.aGrammarError.nErrorStart, aPortion.aGrammarError.nErrorLength );
1535  aPortion.xGrammarChecker = pGrammarResult->xProofreader;
1536  const beans::PropertyValue* pProperties = pGrammarResult->aProperties.getConstArray();
1537  for( sal_Int32 nProp = 0; nProp < pGrammarResult->aProperties.getLength(); ++nProp )
1538  {
1539  if ( pProperties->Name == "DialogTitle" )
1540  {
1541  pProperties->Value >>= aPortion.sDialogTitle;
1542  break;
1543  }
1544  }
1545  }
1546  }
1547  else
1548  aPortion.sText = sText;
1549  aPortion.eLanguage = lcl_GetLanguage(*GetSh());
1550  aPortion.bIsField = bIsField;
1551  aPortion.bIsHidden = bIsHidden;
1552  aPortion.xAlternatives = xAlt;
1553  SpellContentPosition aPosition;
1554  SwPaM *pCursor = GetSh()->GetCursor();
1555  aPosition.nLeft = pCursor->Start()->nContent.GetIndex();
1556  aPosition.nRight = pCursor->End()->nContent.GetIndex();
1557  aLastPortions.push_back(aPortion);
1558  aLastPositions.push_back(aPosition);
1559 
1560 }
1561 
1562 void SwSpellIter::AddPortion(uno::Reference< XSpellAlternatives > const & xAlt,
1563  linguistic2::ProofreadingResult* pGrammarResult,
1564  const SpellContentPositions& rDeletedRedlines)
1565 {
1566  SwEditShell *pMySh = GetSh();
1567  OUString sText;
1568  pMySh->GetSelectedText( sText );
1569  if(!sText.isEmpty())
1570  {
1571  if(xAlt.is() || pGrammarResult != nullptr)
1572  {
1573  CreatePortion(xAlt, pGrammarResult, false, false);
1574  }
1575  else
1576  {
1577  SwPaM *pCursor = GetSh()->GetCursor();
1578  if ( *pCursor->GetPoint() > *pCursor->GetMark() )
1579  pCursor->Exchange();
1580  // save the start and end positions
1581  SwPosition aStart(*pCursor->GetPoint());
1582  SwPosition aEnd(*pCursor->GetMark());
1583  // iterate over the text to find changes in language
1584  // set the mark equal to the point
1585  *pCursor->GetMark() = aStart;
1586  SwTextNode* pTextNode = pCursor->GetNode().GetTextNode();
1587  LanguageType eStartLanguage = lcl_GetLanguage(*GetSh());
1589  rDeletedRedlines, aStart.nContent.GetIndex() );
1590  if( aNextRedline.nLeft == aStart.nContent.GetIndex() )
1591  {
1592  // select until the end of the current redline
1593  const sal_Int32 nEnd = aEnd.nContent.GetIndex() < aNextRedline.nRight ?
1594  aEnd.nContent.GetIndex() : aNextRedline.nRight;
1595  pCursor->GetPoint()->nContent.Assign( pTextNode, nEnd );
1596  CreatePortion(xAlt, pGrammarResult, false, true);
1597  aStart = *pCursor->End();
1598  // search for next redline
1599  aNextRedline = lcl_FindNextDeletedRedline(
1600  rDeletedRedlines, aStart.nContent.GetIndex() );
1601  }
1602  while(*pCursor->GetPoint() < aEnd)
1603  {
1604  // #125786 in table cell with fixed row height the cursor might not move forward
1605  if(!GetSh()->Right(1, CRSR_SKIP_CELLS))
1606  break;
1607 
1608  bool bField = false;
1609  // read the character at the current position to check if it's a field
1610  sal_Unicode const cChar =
1611  pTextNode->GetText()[pCursor->GetMark()->nContent.GetIndex()];
1612  if( CH_TXTATR_BREAKWORD == cChar || CH_TXTATR_INWORD == cChar)
1613  {
1614  const SwTextAttr* pTextAttr = pTextNode->GetTextAttrForCharAt(
1615  pCursor->GetMark()->nContent.GetIndex() );
1616  const sal_uInt16 nWhich = pTextAttr
1617  ? pTextAttr->Which()
1618  : static_cast<sal_uInt16>(RES_TXTATR_END);
1619  switch (nWhich)
1620  {
1621  case RES_TXTATR_FIELD:
1622  case RES_TXTATR_ANNOTATION:
1623  case RES_TXTATR_FTN:
1624  case RES_TXTATR_FLYCNT:
1625  bField = true;
1626  break;
1627  }
1628  }
1629  else if (cChar == CH_TXT_ATR_FORMELEMENT)
1630  {
1631  SwPosition aPos(*pCursor->GetMark());
1632  bField = pMySh->GetDoc()->getIDocumentMarkAccess()->getDropDownFor(aPos);
1633  }
1634 
1635  LanguageType eCurLanguage = lcl_GetLanguage(*GetSh());
1636  bool bRedline = aNextRedline.nLeft == pCursor->GetPoint()->nContent.GetIndex();
1637  // create a portion if the next character
1638  // - is a field,
1639  // - is at the beginning of a deleted redline
1640  // - has a different language
1641  if(bField || bRedline || eCurLanguage != eStartLanguage)
1642  {
1643  eStartLanguage = eCurLanguage;
1644  // go one step back - the cursor currently selects the first character
1645  // with a different language
1646  // in the case of redlining it's different
1647  if(eCurLanguage != eStartLanguage || bField)
1648  *pCursor->GetPoint() = *pCursor->GetMark();
1649  // set to the last start
1650  *pCursor->GetMark() = aStart;
1651  // create portion should only be called if a selection exists
1652  // there's no selection if there's a field at the beginning
1653  if(*pCursor->Start() != *pCursor->End())
1654  CreatePortion(xAlt, pGrammarResult, false, false);
1655  aStart = *pCursor->End();
1656  // now export the field - if there is any
1657  if(bField)
1658  {
1659  *pCursor->GetMark() = *pCursor->GetPoint();
1660  GetSh()->Right(1, CRSR_SKIP_CELLS);
1661  CreatePortion(xAlt, pGrammarResult, true, false);
1662  aStart = *pCursor->End();
1663  }
1664  }
1665  // if a redline start then create a portion for it
1666  if(bRedline)
1667  {
1668  *pCursor->GetMark() = *pCursor->GetPoint();
1669  // select until the end of the current redline
1670  const sal_Int32 nEnd = aEnd.nContent.GetIndex() < aNextRedline.nRight ?
1671  aEnd.nContent.GetIndex() : aNextRedline.nRight;
1672  pCursor->GetPoint()->nContent.Assign( pTextNode, nEnd );
1673  CreatePortion(xAlt, pGrammarResult, false, true);
1674  aStart = *pCursor->End();
1675  // search for next redline
1676  aNextRedline = lcl_FindNextDeletedRedline(
1677  rDeletedRedlines, aStart.nContent.GetIndex() );
1678  }
1679  *pCursor->GetMark() = *pCursor->GetPoint();
1680  }
1681  pCursor->SetMark();
1682  *pCursor->GetMark() = aStart;
1683  CreatePortion(xAlt, pGrammarResult, false, false);
1684  }
1685  }
1686 }
1687 
1689 {
1690  SwTextNode *pNode;
1691  SwWrongList *pWrong;
1692  SwNodeIndex aIdx = rErrorPosition.Start()->nNode;
1693  SwNodeIndex aEndIdx = rErrorPosition.Start()->nNode;
1694  sal_Int32 nStart = rErrorPosition.Start()->nContent.GetIndex();
1695  sal_Int32 nEnd = COMPLETE_STRING;
1696  while( aIdx <= aEndIdx )
1697  {
1698  pNode = aIdx.GetNode().GetTextNode();
1699  if( pNode ) {
1700  if( aIdx == aEndIdx )
1701  nEnd = rErrorPosition.End()->nContent.GetIndex();
1702  pWrong = pNode->GetGrammarCheck();
1703  if( pWrong )
1704  pWrong->RemoveEntry( nStart, nEnd );
1705  pWrong = pNode->GetWrong();
1706  if( pWrong )
1707  pWrong->RemoveEntry( nStart, nEnd );
1709  }
1710  ++aIdx;
1711  nStart = 0;
1712  }
1713 }
1714 
1715 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SpellContentPositions aLastPositions
Definition: edlingu.cxx:116
const sal_Char * pChar
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:149
void DeleteMark()
Definition: pam.hxx:177
void KillPams()
Definition: crsrsh.cxx:1010
sal_uLong GetIndex() const
Definition: node.hxx:282
std::function< SwTextFrame *()> Creator
Definition: splargs.hxx:148
SwNode & GetNode(bool bPoint=true) const
Definition: pam.hxx:223
void ShowSelection()
Definition: edlingu.cxx:414
Marks a position in the document model.
Definition: pam.hxx:35
void DelSoftHyph(const sal_Int32 nStart, const sal_Int32 nEnd)
Definition: thints.cxx:1744
#define RES_CHRATR_CJK_LANGUAGE
Definition: hintids.hxx:92
bool Right(sal_uInt16 nCnt, sal_uInt16 nMode, bool bAllowVisual=false)
Definition: crsrsh.hxx:353
void FillFindPos(SwDocPositions ePos, SwPosition &rPos) const
Definition: swcrsr.cxx:1076
SwRect & Union(const SwRect &rRect)
Definition: swrect.cxx:42
SwPaM * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:185
#define UPN_IS_HYPH_AUTO
#define RES_CHRATR_LANGUAGE
Definition: hintids.hxx:78
const OUString & GetText() const
Definition: ndtxt.hxx:211
static bool HasConvIter()
Is text conversion active somewhere else?
Definition: edlingu.cxx:600
#define UPN_MAX_NUMBER_OF_SUGGESTIONS
SwEditShell * GetSh()
Definition: edlingu.cxx:79
uno::Reference< XSpellChecker1 > xSpeller
Definition: edlingu.cxx:113
stay with the cursor inside text
Definition: crstate.hxx:125
css::uno::Any Spell(SwPaM &, css::uno::Reference< css::linguistic2::XSpellChecker1 > const &, sal_uInt16 *pPageCnt, sal_uInt16 *pPageSt, bool bGrammarCheck, SwRootFrame const *pLayout, SwConversionArgs *pConvArgs=nullptr) const
Operations on the content of the document e.g.
Definition: docedt.cxx:500
SwNodeIndex nNode
Definition: pam.hxx:37
bool IsTableMode() const
Definition: crsrsh.hxx:643
SwConvIter(SwConversionArgs &rConvArgs)
Definition: edlingu.cxx:145
void GetSelectedText(OUString &rBuf, ParaBreakType nHndlParaBreak=ParaBreakType::ToBlank)
Query text within selection.
Definition: edglss.cxx:253
static void repaintTextFrames(const SwTextNode &rNode)
Repaint all text frames of the given text node.
Definition: txtfrm.cxx:4006
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 bOldIdle
Definition: edlingu.cxx:162
bool GoEndSentence()
Definition: crstrvl1.cxx:73
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1150
bool SpellSentence(svx::SpellPortions &rToFill, bool bIsGrammarCheck)
Spells on a sentence basis - the SpellPortions are needed.
Definition: edlingu.cxx:1029
bool m_bRealWidth
Calculation of the width required.
Definition: crstate.hxx:147
SwCursor * GetSwCursor() const
Definition: crsrsh.hxx:864
Definition: doc.hxx:185
css::uno::Reference< css::linguistic2::XProofreader > xGrammarChecker
void InsertSoftHyph(const sal_Int32 nHyphPos)
Definition: edlingu.cxx:529
void ToSentenceStart()
Definition: edlingu.cxx:1492
SwNode & GetNode() const
Definition: ndindex.hxx:118
void DestroyCursor()
transform TableCursor to normal cursor, nullify Tablemode
Definition: crsrsh.cxx:142
void End_(bool bRestoreSelection=true)
Definition: edlingu.cxx:249
void Pos(const Point &rNew)
Definition: swrect.hxx:167
IDocumentMarkAccess * getIDocumentMarkAccess()
Definition: docbm.cxx:1348
Dialog to specify the properties of drop-down form field.
Definition: accfrmobj.cxx:40
void HyphIgnore()
ignore hyphenation
Definition: edlingu.cxx:809
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
sal_uInt16 Which() const
Definition: txatbase.hxx:105
void ApplyChangedSentence(const svx::SpellPortions &rNewPortions, bool bRecheck)
Applies a changed sentence.
Definition: edlingu.cxx:1068
static bool HasHyphIter()
Is hyphenation active somewhere else?
Definition: edlingu.cxx:605
std::unique_ptr< SwPosition > m_pStart
Definition: edlingu.cxx:71
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:347
#define RES_TXTATR_END
Definition: hintids.hxx:158
virtual ::sw::mark::IFieldmark * getDropDownFor(const SwPosition &pos) const =0
uno::Reference< linguistic2::XLinguProperties > GetLinguPropertySet()
Definition: swtypes.cxx:81
void CalcStartEnd(sal_uLong nNdIdx, sal_Int32 &rStart, sal_Int32 &rEnd) const
Calculates the intersection with text node number nNdIdx.
Definition: docredln.cxx:1317
void RemoveEntry(sal_Int32 nBegin, sal_Int32 nEnd)
Definition: wrong.cxx:585
#define CH_TXT_ATR_FORMELEMENT
Definition: hintids.hxx:50
static SwConvIter * g_pConvIter
Definition: edlingu.cxx:181
OUString sDialogTitle
bool HasSelection() const
Does the current cursor create a selection?
Definition: crsrsh.cxx:2408
static bool IsShowChanges(const RedlineFlags eM)
bool IsSymbolAt(sal_Int32 nBegin) const
in ndcopy.cxx
Definition: itratr.cxx:840
void CreatePortion(uno::Reference< XSpellAlternatives > const &xAlt, linguistic2::ProofreadingResult *pGrammarResult, bool bIsField, bool bIsHidden)
create a text portion at the given position
Definition: edlingu.cxx:1515
#define CHAR_SOFTHYPHEN
Definition: swtypes.hxx:174
size_type size() const
Definition: docary.hxx:368
SwMoveFnCollection const & MakeFindRange(SwDocPositions, SwDocPositions, SwPaM *) const
Definition: crsrsh.hxx:858
SwDocPositions
Definition: cshtyp.hxx:103
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
SwTextFrame * m_pLastFrame
Definition: edlingu.cxx:159
bool GoStartSentence()
Definition: crstrvl1.cxx:78
SwTextAttr * GetTextAttrForCharAt(const sal_Int32 nIndex, const sal_uInt16 nWhich=RES_TXTATR_END) const
get the text attribute at position nIndex which owns the dummy character CH_TXTATR_* at that position...
Definition: ndtxt.cxx:3060
#define CH_TXTATR_BREAKWORD
Definition: hintids.hxx:43
sal_uInt16 sal_Unicode
void HyphStart(SwDocPositions eStart, SwDocPositions eEnd)
Save selections.
Definition: edlingu.cxx:742
static void InsertSoftHyph(const sal_Int32 nHyphPos)
For Inserting SoftHyphen. Position is offset within the syllabificated word.
Definition: edlingu.cxx:802
#define CH_TXTATR_INWORD
Definition: hintids.hxx:44
void StartProgress(const char *pMessResId, long nStartValue, long nEndValue, SwDocShell *pDocShell)
Definition: mainwn.cxx:48
rtl::Reference< SwDoc > mxDoc
The document; never 0.
Definition: viewsh.hxx:174
SwIndex nContent
Definition: pam.hxx:38
uno::Any Continue(sal_uInt16 *pPageCnt, sal_uInt16 *pPageSt)
Definition: edlingu.cxx:348
sal_uInt16 & GetCursorCnt()
Definition: edlingu.cxx:93
css::uno::Reference< css::uno::XInterface > HyphContinue(sal_uInt16 *pPageCnt, sal_uInt16 *pPageSt)
Definition: edlingu.cxx:766
SwDoc * GetDoc() const
Definition: viewsh.hxx:284
SwPaM * GetNext()
Definition: pam.hxx:264
virtual bool GetCharRect(SwRect &, const SwPosition &, SwCursorMoveState *=nullptr, bool bAllowFarAway=true) const
Definition: unusedf.cxx:71
bool bBackToStartOfSentence
Definition: edlingu.cxx:117
static void DelSoftHyph(SwPaM &rPam)
Definition: edlingu.cxx:520
bool GetGrammarCorrection(css::linguistic2::ProofreadingResult &rResult, sal_Int32 &rErrorPosInText, sal_Int32 &rErrorIndexInResult, css::uno::Sequence< OUString > &rSuggestions, const Point *pPt, SwRect &rSelectRect)
Definition: edlingu.cxx:949
used for text conversion
Definition: edlingu.cxx:141
SwEditShell * pSh
Definition: edlingu.cxx:70
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
const SfxItemPool & GetAttrPool() const
Definition: viewsh.hxx:614
virtual SwRedlineTable::size_type GetRedlinePos(const SwNode &rNode, RedlineType nType) const =0
virtual bool InsertString(const SwPaM &rRg, const OUString &, const SwInsertFlags nInsertMode=SwInsertFlags::EMPTYEXPAND)=0
Insert string into existing text node at position rRg.Point().
bool LeftMargin()
Definition: crsrsh.hxx:357
SvtScriptType
const OUString & getViewText() const
const svx::SpellPortions & GetLastPortions() const
Definition: edlingu.cxx:136
SvtScriptType GetScriptType() const
returns the script type of the selection
Definition: edattr.cxx:671
#define SAL_MAX_INT32
void SpellEnd(SwConversionArgs const *pConvArgs=nullptr, bool bRestoreSelection=true)
Restore selections.
Definition: edlingu.cxx:655
void Start(SwEditShell *pSh, SwDocPositions eStart, SwDocPositions eEnd)
Definition: edlingu.cxx:271
const SwPosition * GetPoint() const
Definition: pam.hxx:207
std::unique_ptr< SwPosition > m_pEnd
Definition: edlingu.cxx:72
void EndAction(const bool bIdleEnd=false, const bool DoSetPosX=false)
Definition: crsrsh.cxx:229
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:198
#define RES_TXTATR_FTN
Definition: hintids.hxx:152
void Push()
store a copy of the current cursor on the cursor stack
Definition: crsrsh.cxx:2143
void Exchange()
Definition: pam.cxx:471
int i
void SetAttrItem(const SfxPoolItem &, SetAttrMode nFlags=SetAttrMode::DEFAULT, const bool bParagraphSetting=false)
Definition: edatmisc.cxx:113
bool IsIdle() const
Definition: viewopt.hxx:201
SwContentNode * GetContentNode()
Definition: node.hxx:615
css::uno::Reference< css::linguistic2::XSpellAlternatives > GetCorrection(const Point *pPt, SwRect &rSelectRect)
Get a list of potential corrections for misspelled word.
Definition: edlingu.cxx:889
vector_type::size_type size_type
Definition: docary.hxx:330
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:205
css::uno::Any SpellContinue(sal_uInt16 *pPageCnt, sal_uInt16 *pPageSt, SwConversionArgs const *pConvArgs)
Definition: edlingu.cxx:672
static sal_Int16 GetI18NScriptTypeOfLanguage(LanguageType nLang)
bool RightMargin(bool bAPI=false)
Definition: crsrsh.hxx:358
Marks a character position inside a document model node.
Definition: index.hxx:37
SwGrammarMarkUp * GetGrammarCheck()
Definition: txtedt.cxx:2189
void SetEnd(SwPosition *pNew)
Definition: edlingu.cxx:82
const SwPosition * GetCurrX() const
Definition: edlingu.cxx:90
#define SET_CURR_SHELL(shell)
Definition: swtypes.hxx:101
sal_uInt16 GetCursorCnt(bool bAll=true) const
Get the number of elements in the ring of cursors.
Definition: crsrsh.cxx:2617
Marks a node in the document model.
Definition: ndindex.hxx:31
std::unique_ptr< SwPosition > m_pCurrX
Definition: edlingu.cxx:74
static LanguageType lcl_GetLanguage(SwEditShell &rSh)
Definition: edlingu.cxx:1497
const SwPosition * GetStart() const
Definition: edlingu.cxx:84
const SwPosition * GetEnd() const
Definition: edlingu.cxx:81
static SpellContentPositions lcl_CollectDeletedRedlines(SwEditShell const *pSh)
Collect all deleted redlines of the current text node beginning at the start of the cursor position...
Definition: edlingu.cxx:1220
void TableCursorToCursor()
enter block mode, change normal cursor into block cursor
Definition: crsrsh.cxx:884
void AddPortion(uno::Reference< XSpellAlternatives > const &xAlt, linguistic2::ProofreadingResult *pGrammarResult, const SpellContentPositions &rDeletedRedlines)
Definition: edlingu.cxx:1562
const SwPosition * Start() const
Definition: pam.hxx:212
void HandleCorrectionError(const OUString &aText, SwPosition aPos, sal_Int32 nBegin, sal_Int32 nLen, const Point *pPt, SwRect &rSelectRect)
Definition: edlingu.cxx:821
static void MoveContinuationPosToEndOfCheckedSentence()
Moves the continuation position to the end of the currently checked sentence.
Definition: edlingu.cxx:1058
bool IsInProtectSect() const
Is node in an protected area?
Definition: node.cxx:410
void SetCurr(SwPosition *pNew)
Definition: edlingu.cxx:88
void SetLinguRange(SwDocPositions eStart, SwDocPositions eEnd)
Definition: edlingu.cxx:610
void SetStart(SwPosition *pNew)
Definition: edlingu.cxx:85
void Start(SwEditShell *pSh, SwDocPositions eStart, SwDocPositions eEnd)
Definition: edlingu.cxx:426
void StartAction()
Definition: crsrsh.cxx:212
svx::SpellPortions aLastPortions
Definition: edlingu.cxx:114
const sal_uInt16 CRSR_SKIP_CELLS
Definition: swcrsr.hxx:64
static SwSpellIter * g_pSpellIter
Definition: edlingu.cxx:180
sal_Int32 getSentenceStart(sal_Int32 nPos)
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
LanguageType GetLanguage() const
static bool IsAuto()
Definition: edlingu.cxx:407
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:367
#define RES_TXTATR_FIELD
Definition: hintids.hxx:150
#define RES_CHRATR_CTL_LANGUAGE
Definition: hintids.hxx:97
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:426
bool ExtendSelection(bool bEnd=true, sal_Int32 nCount=1)
extend current SSelection by n characters
Definition: crsrsh.cxx:2511
#define RES_TXTATR_ANNOTATION
Definition: hintids.hxx:153
void SetIdle(bool b) const
Definition: viewopt.hxx:208
const SwTextNode * m_pLastNode
Definition: edlingu.cxx:158
std::vector< SpellContentPosition > SpellContentPositions
Definition: edlingu.cxx:109
css::uno::Reference< css::linguistic2::XSpellAlternatives > xAlternatives
sal_Int32 GetIndex() const
Definition: index.hxx:95
bool InWrongWord(sal_Int32 &rChk, sal_Int32 &rLn) const
If a word is incorrectly selected, this method returns begin and length of it.
Definition: wrong.cxx:102
static SwHyphIter * g_pHyphIter
Definition: edlingu.cxx:182
const SpellContentPositions & GetLastPositions() const
Definition: edlingu.cxx:137
const SwPosition * End() const
Definition: pam.hxx:217
uno::Reference< linguistic2::XSpellChecker1 > GetSpellChecker()
Definition: swtypes.cxx:66
static void IgnoreGrammarErrorAt(SwPaM &rErrorPosition)
Definition: edlingu.cxx:1688
void SpellStart(SwDocPositions eStart, SwDocPositions eEnd, SwDocPositions eCurr, SwConversionArgs *pConvArgs=nullptr)
Functions used for spell checking and text conversion.
Definition: edlingu.cxx:618
LanguageType GetLang(const sal_Int32 nBegin, const sal_Int32 nLen=0, sal_uInt16 nScript=0) const
Definition: thints.cxx:3361
const SwRect & GetCharRect() const
Definition: crsrsh.hxx:518
RedlineType GetType(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1780
void HyphEnd()
restore selections.
Definition: edlingu.cxx:753
static SpellContentPosition lcl_FindNextDeletedRedline(const SpellContentPositions &rDeletedRedlines, sal_Int32 nSearchFrom)
Definition: edlingu.cxx:1275
SwWrongList * GetWrong()
Definition: txtedt.cxx:2166
#define RES_TXTATR_FLYCNT
Definition: hintids.hxx:151
void ClearMark()
Definition: crsrsh.cxx:927
bool GetCurAttr(SfxItemSet &, const bool bMergeIndentValuesOfNumRule=false) const
Definition: edattr.cxx:181
void Start(SwEditShell *pSh, SwDocPositions eStart, SwDocPositions eEnd)
Definition: edlingu.cxx:340
SwConversionArgs & rArgs
Definition: edlingu.cxx:143
static sal_uInt32 lcl_CountRedlines(const svx::SpellPortions &rLastPortions)
Definition: edlingu.cxx:1052
sal_Int32 getSentenceEnd(sal_Int32 nPos)
css::linguistic2::SingleProofreadingError aGrammarError
void SetCurrX(SwPosition *pNew)
Definition: edlingu.cxx:91
LanguageType eLanguage
virtual RedlineFlags GetRedlineFlags() const =0
Query the currently set redline mode.
static void PutSpellingToSentenceStart()
Make SpellIter start with the current sentence when called next time.
Definition: edlingu.cxx:1044
std::unique_ptr< SwPosition > m_pCurr
Definition: edlingu.cxx:73
const SwPosition * GetCurr() const
Definition: edlingu.cxx:87
std::vector< SpellPortion > SpellPortions
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:457
SwTextFrame * SwHyphIterCacheLastTextFrame(SwTextNode const *pNode, const sw::Creator &create)
Definition: edlingu.cxx:569
bool Pop(PopMode)
delete cursor
Definition: crsrsh.cxx:2165
static void lcl_CutRedlines(SpellContentPositions &aDeletedRedlines, SwEditShell const *pSh)
remove the redline positions after the current selection
Definition: edlingu.cxx:1260
virtual const SwRedlineTable & GetRedlineTable() const =0
SwRootFrame * GetLayout() const
Definition: viewsh.cxx:2072
void Start_(SwEditShell *pSh, SwDocPositions eStart, SwDocPositions eEnd)
Definition: edlingu.cxx:191
bool SpellSentence(svx::SpellPortions &rPortions, bool bIsGrammarCheck)
Definition: edlingu.cxx:1291
uno::Any Continue(sal_uInt16 *pPageCnt, sal_uInt16 *pPageSt)
Definition: edlingu.cxx:450
sal_uInt16 GetPageNum() const
Definition: rootfrm.hxx:307
sal_uInt16 mnStartAction
!= 0 if at least one Action is active.
Definition: viewsh.hxx:176
const sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:61
css::uno::Reference< css::linguistic2::XHyphenatedWord > Hyphenate(SwPaM *pPam, const Point &rCursorPos, sal_uInt16 *pPageCnt, sal_uInt16 *pPageSt)
Definition: docedt.cxx:792
uno::Any Continue(sal_uInt16 *pPageCnt, sal_uInt16 *pPageSt)
Definition: edlingu.cxx:285
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:842
sal_uInt16 nCursorCnt
Definition: edlingu.cxx:75
void End()
Definition: edlingu.cxx:442
void Ignore()
ignore hyphenation
Definition: edlingu.cxx:507
css::uno::Any SAL_CALL makeAny(const SharedUNOComponent< INTERFACE, COMPONENT > &value)