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