LibreOffice Module sw (master)  1
wrong.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 <swtypes.hxx>
21 
22 #include <SwGrammarMarkUp.hxx>
23 #include <ndtxt.hxx>
24 #include <txtfrm.hxx>
25 
26 #include <osl/diagnose.h>
27 
28 SwWrongArea::SwWrongArea( const OUString& rType, WrongListType listType,
29  css::uno::Reference< css::container::XStringKeyMap > const & xPropertyBag,
30  sal_Int32 nPos,
31  sal_Int32 nLen)
32 : maType(rType), mnPos(nPos), mnLen(nLen), mpSubList(nullptr)
33 {
34  mColor = getWrongAreaColor(listType, xPropertyBag);
35  mLineType = getWrongAreaLineType(listType, xPropertyBag);
36 }
37 
38 SwWrongArea::SwWrongArea( const OUString& rType,
39  css::uno::Reference< css::container::XStringKeyMap > const & xPropertyBag,
40  sal_Int32 nPos,
41  sal_Int32 nLen,
42  SwWrongList* pSubList)
43 : maType(rType), mnPos(nPos), mnLen(nLen), mpSubList(pSubList), mLineType(WRONGAREA_NONE)
44 {
45  if (pSubList != nullptr)
46  {
47  mColor = getWrongAreaColor(pSubList->GetWrongListType(), xPropertyBag);
48  mLineType = getWrongAreaLineType(pSubList->GetWrongListType(), xPropertyBag);
49  }
50 }
51 
53  meType (eType),
54  mnBeginInvalid(COMPLETE_STRING), // everything correct... (the invalid area starts beyond the string)
55  mnEndInvalid (COMPLETE_STRING)
56 {
57  maList.reserve( 5 );
58 }
59 
61 {
62  ClearList();
63 }
64 
66 {
67  SwWrongList* pClone = new SwWrongList( meType );
68  pClone->CopyFrom( *this );
69  return pClone;
70 }
71 
72 void SwWrongList::CopyFrom( const SwWrongList& rCopy )
73 {
74  maList = rCopy.maList;
75  meType = rCopy.meType;
77  mnEndInvalid = rCopy.mnEndInvalid;
78  for(SwWrongArea & i : maList)
79  {
80  if( i.mpSubList )
81  i.mpSubList = i.mpSubList->Clone();
82  }
83 }
84 
86 {
87  for (SwWrongArea & i : maList)
88  {
89  delete i.mpSubList;
90  i.mpSubList = nullptr;
91  }
92  maList.clear();
93 }
94 
102 bool SwWrongList::InWrongWord( sal_Int32 &rChk, sal_Int32 &rLn ) const
103 {
104  const sal_uInt16 nPos = GetWrongPos( rChk );
105  if ( nPos >= Count() )
106  return false;
107  const sal_Int32 nWrPos = Pos( nPos );
108  if ( nWrPos <= rChk )
109  {
110  rLn = Len( nPos );
111  if( nWrPos + rLn <= rChk )
112  return false;
113  rChk = nWrPos;
114  return true;
115  }
116  return false;
117 }
118 
126 bool SwWrongList::Check( sal_Int32 &rChk, sal_Int32 &rLn ) const
127 {
128  sal_uInt16 nPos = GetWrongPos( rChk );
129  rLn += rChk;
130 
131  if( nPos == Count() )
132  return false;
133 
134  sal_Int32 nWrPos = Pos( nPos );
135  sal_Int32 nEnd = nWrPos + Len( nPos );
136  if( nEnd == rChk )
137  {
138  ++nPos;
139  if( nPos == Count() )
140  return false;
141 
142  nWrPos = Pos( nPos );
143  nEnd = nWrPos + Len( nPos );
144  }
145  if( nEnd > rChk && nWrPos < rLn )
146  {
147  if( nWrPos > rChk )
148  rChk = nWrPos;
149  if( nEnd < rLn )
150  rLn = nEnd;
151  rLn -= rChk;
152  return 0 != rLn;
153  }
154  return false;
155 }
156 
163 sal_Int32 SwWrongList::NextWrong( sal_Int32 nChk ) const
164 {
165  sal_Int32 nRet = COMPLETE_STRING;
166  sal_uInt16 nPos = GetWrongPos( nChk );
167  if( nPos < Count() )
168  {
169  nRet = Pos( nPos );
170  if( nRet < nChk && nRet + Len( nPos ) <= nChk )
171  {
172  if( ++nPos < Count() )
173  nRet = Pos( nPos );
174  else
175  nRet = COMPLETE_STRING;
176  }
177  }
178  if( nRet > GetBeginInv() && nChk < GetEndInv() )
179  nRet = std::max(nChk, GetBeginInv());
180  return nRet;
181 }
182 
190 sal_uInt16 SwWrongList::GetWrongPos( sal_Int32 nValue ) const
191 {
192  sal_uInt16 nMax = Count();
193  sal_uInt16 nMin = 0;
194 
195  if( nMax > 0 )
196  {
197  // For smart tag lists, we may not use a binary search. We return the
198  // position of the first smart tag which covers nValue
199  if ( !maList[0].maType.isEmpty() || maList[0].mpSubList )
200  {
201  auto aIter = std::find_if(maList.begin(), maList.end(),
202  [nValue](const SwWrongArea& rST) {
203  return (rST.mnPos <= nValue && nValue < rST.mnPos + rST.mnLen)
204  || (rST.mnPos > nValue);
205  });
206  return static_cast<sal_uInt16>(std::distance(maList.begin(), aIter));
207  }
208 
209  --nMax;
210  sal_uInt16 nMid = 0;
211  while( nMin <= nMax )
212  {
213  nMid = nMin + ( nMax - nMin ) / 2;
214  const sal_Int32 nTmp = Pos( nMid );
215  if( nTmp == nValue )
216  {
217  nMin = nMid;
218  break;
219  }
220  else if( nTmp < nValue )
221  {
222  if( nTmp + Len( nMid ) >= nValue )
223  {
224  nMin = nMid;
225  break;
226  }
227  nMin = nMid + 1;
228  }
229  else if( nMid == 0 )
230  {
231  break;
232  }
233  else
234  nMax = nMid - 1;
235  }
236  }
237 
238  // nMin now points to an index i into the wrong list which
239  // 1. nValue is inside [ Area[i].pos, Area[i].pos + Area[i].len ] (inclusive!!!)
240  // 2. nValue < Area[i].pos
241 
242  return nMin;
243 }
244 
245 void SwWrongList::Invalidate_( sal_Int32 nBegin, sal_Int32 nEnd )
246 {
247  if ( nBegin < GetBeginInv() )
248  mnBeginInvalid = nBegin;
249  if ( nEnd > GetEndInv() || GetEndInv() == COMPLETE_STRING )
250  mnEndInvalid = nEnd;
251 }
252 
253 void SwWrongList::SetInvalid( sal_Int32 nBegin, sal_Int32 nEnd )
254 {
255  mnBeginInvalid = nBegin;
256  mnEndInvalid = nEnd;
257 }
258 
266 void SwWrongList::Move( sal_Int32 nPos, sal_Int32 nDiff )
267 {
268  sal_uInt16 i = GetWrongPos( nPos );
269  if( nDiff < 0 )
270  {
271  const sal_Int32 nEnd = nPos - nDiff;
272  sal_uInt16 nLst = i;
273  bool bJump = false;
274  while( nLst < Count() && Pos( nLst ) < nEnd )
275  ++nLst;
276  if( nLst > i )
277  {
278  const sal_Int32 nWrPos = Pos( nLst - 1 );
279  if ( nWrPos <= nPos )
280  {
281  sal_Int32 nWrLen = Len( nLst - 1 );
282  // calculate new length of word
283  nWrLen = ( nEnd > nWrPos + nWrLen ) ?
284  nPos - nWrPos :
285  nWrLen + nDiff;
286  if( nWrLen )
287  {
288  maList[--nLst].mnLen = nWrLen;
289  bJump = true;
290  }
291  }
292  }
293  Remove( i, nLst - i );
294 
295  if ( bJump )
296  ++i;
297  if( COMPLETE_STRING == GetBeginInv() )
298  SetInvalid( nPos ? nPos - 1 : nPos, nPos + 1 );
299  else
300  {
301  ShiftLeft( mnBeginInvalid, nPos, nEnd );
303  ShiftLeft( mnEndInvalid, nPos, nEnd );
304  Invalidate_( nPos ? nPos - 1 : nPos, nPos + 1 );
305  }
306  }
307  else
308  {
309  const sal_Int32 nEnd = nPos + nDiff;
310  if( COMPLETE_STRING != GetBeginInv() )
311  {
312  if( mnBeginInvalid > nPos )
313  mnBeginInvalid += nDiff;
314  if( mnEndInvalid >= nPos && mnEndInvalid != COMPLETE_STRING )
315  mnEndInvalid += nDiff;
316  }
317  // If the pointer is in the middle of a wrong word,
318  // invalidation must happen from the beginning of that word.
319  if( i < Count() )
320  {
321  const sal_Int32 nWrPos = Pos( i );
322  if (nPos >= nWrPos)
323  {
324  Invalidate( nWrPos, nEnd );
325  const sal_Int32 nWrLen = Len( i ) + nDiff;
326  maList[i++].mnLen = nWrLen;
327  Invalidate( nWrPos, nWrPos + nWrLen );
328  }
329  }
330  else
331  Invalidate( nPos, nEnd );
332  }
333  while( i < Count() )
334  {
335  maList[i++].mnPos += nDiff;
336  }
337 }
338 
339 // TODO: Complete documentation
355 auto SwWrongList::Fresh( sal_Int32 &rStart, sal_Int32 &rEnd, sal_Int32 nPos,
356  sal_Int32 nLen, sal_uInt16 nIndex, sal_Int32 nCursorPos ) -> FreshState
357 {
358  // length of word must be greater than 0
359  // only report a spelling error if the cursor position is outside the word,
360  // so that the user is not annoyed while typing
361  FreshState eRet = nLen
362  ? (nCursorPos > nPos + nLen || nCursorPos < nPos)
363  ? FreshState::FRESH
364  : FreshState::CURSOR
365  : FreshState::NOTHING;
366 
367  sal_Int32 nWrPos = 0;
368  sal_Int32 nWrEnd = rEnd;
369  sal_uInt16 nCnt = nIndex;
370  if( nCnt < Count() )
371  {
372  nWrPos = Pos( nCnt );
373  if( nWrPos < nPos && rStart > nWrPos )
374  rStart = nWrPos;
375  }
376 
377  while( nCnt < Count() )
378  {
379  nWrPos = Pos( nCnt );
380  if ( nWrPos >= nPos )
381  break;
382  nWrEnd = nWrPos + Len( nCnt++ );
383  }
384 
385  if( nCnt < Count() && nWrPos == nPos && Len( nCnt ) == nLen )
386  {
387  ++nCnt;
388  eRet = FreshState::FRESH;
389  }
390  else
391  {
392  if (FreshState::FRESH == eRet)
393  {
394  if( rStart > nPos )
395  rStart = nPos;
396  nWrEnd = nPos + nLen;
397  }
398  }
399 
400  nPos += nLen;
401 
402  if( nCnt < Count() )
403  {
404  nWrPos = Pos( nCnt );
405  if( nWrPos < nPos && rStart > nWrPos )
406  rStart = nWrPos;
407  }
408 
409  while( nCnt < Count() )
410  {
411  nWrPos = Pos( nCnt );
412  if ( nWrPos >= nPos )
413  break;
414  nWrEnd = nWrPos + Len( nCnt++ );
415  }
416 
417  if( rEnd < nWrEnd )
418  rEnd = nWrEnd;
419 
420  Remove( nIndex, nCnt - nIndex );
421 
422  return eRet;
423 }
424 
425 void SwWrongList::Invalidate( sal_Int32 nBegin, sal_Int32 nEnd )
426 {
427  if (COMPLETE_STRING == GetBeginInv())
428  SetInvalid( nBegin, nEnd );
429  else
430  Invalidate_( nBegin, nEnd );
431 }
432 
434 {
435  if( Count() )
436  {
437  const sal_Int32 nFirst = Pos( 0 );
438  const sal_Int32 nLast = Pos( Count() - 1 ) + Len( Count() - 1 );
439  Invalidate( nFirst, nLast );
440  return true;
441  }
442  return false;
443 }
444 
445 SwWrongList* SwWrongList::SplitList( sal_Int32 nSplitPos )
446 {
447  SwWrongList *pRet = nullptr;
448  sal_uInt16 nLst = 0;
449  while( nLst < Count() && Pos( nLst ) < nSplitPos )
450  ++nLst;
451  if( nLst )
452  {
453  sal_Int32 nWrPos = Pos( nLst - 1 );
454  sal_Int32 nWrLen = Len( nLst - 1 );
455  if ( nWrPos+nWrLen > nSplitPos )
456  {
457  nWrLen += nWrPos - nSplitPos;
458  maList[--nLst].mnPos = nSplitPos;
459  maList[nLst].mnLen = nWrLen;
460  }
461  }
462  if( nLst )
463  {
465  pRet = new SwGrammarMarkUp();
466  else
467  pRet = new SwWrongList( GetWrongListType() );
468  pRet->Insert(0, maList.begin(), ( nLst >= maList.size() ? maList.end() : maList.begin() + nLst ) );
469  pRet->SetInvalid( GetBeginInv(), GetEndInv() );
470  pRet->Invalidate_( nSplitPos ? nSplitPos - 1 : nSplitPos, nSplitPos );
471  Remove( 0, nLst );
472  }
473  if( COMPLETE_STRING == GetBeginInv() )
474  SetInvalid( 0, 1 );
475  else
476  {
477  ShiftLeft( mnBeginInvalid, 0, nSplitPos );
479  ShiftLeft( mnEndInvalid, 0, nSplitPos );
480  Invalidate_( 0, 1 );
481  }
482  for (nLst = 0; nLst < Count(); ++nLst )
483  {
484  maList[nLst].mnPos -= nSplitPos;
485  }
486  return pRet;
487 }
488 
489 void SwWrongList::JoinList( SwWrongList* pNext, sal_Int32 nInsertPos )
490 {
491  if (pNext)
492  {
493  OSL_ENSURE( GetWrongListType() == pNext->GetWrongListType(), "type mismatch with next list" );
494 
495  sal_uInt16 nCnt = Count();
496  pNext->Move( 0, nInsertPos );
497  Insert(nCnt, pNext->maList.begin(), pNext->maList.end());
498 
499  Invalidate( pNext->GetBeginInv(), pNext->GetEndInv() );
500  if( nCnt && Count() > nCnt )
501  {
502  sal_Int32 nWrPos = Pos( nCnt );
503  sal_Int32 nWrLen = Len( nCnt );
504  if( !nWrPos )
505  {
506  nWrPos += nInsertPos;
507  nWrLen -= nInsertPos;
508  maList[nCnt].mnPos = nWrPos;
509  maList[nCnt].mnLen = nWrLen;
510  }
511  if( nWrPos == Pos( nCnt - 1 ) + Len( nCnt - 1 ) )
512  {
513  nWrLen += Len( nCnt - 1 );
514  maList[nCnt - 1].mnLen = nWrLen;
515  Remove( nCnt, 1 );
516  }
517  }
518  }
519  Invalidate( nInsertPos ? nInsertPos - 1 : nInsertPos, nInsertPos + 1 );
520 }
521 
522 void SwWrongList::InsertSubList( sal_Int32 nNewPos, sal_Int32 nNewLen, sal_uInt16 nWhere, SwWrongList* pSubList )
523 {
524  if (pSubList)
525  {
526  OSL_ENSURE( GetWrongListType() == pSubList->GetWrongListType(), "type mismatch with sub list" );
527  }
528  std::vector<SwWrongArea>::iterator i = maList.begin();
529  if ( nWhere >= maList.size() )
530  i = maList.end(); // robust
531  else
532  i += nWhere;
533  maList.insert(i, SwWrongArea( OUString(), nullptr, nNewPos, nNewLen, pSubList ) );
534 }
535 
536 // New functions: Necessary because SwWrongList has been changed to use std::vector
537 void SwWrongList::Insert(sal_uInt16 nWhere, std::vector<SwWrongArea>::iterator startPos, std::vector<SwWrongArea>::iterator const & endPos)
538 {
539  std::vector<SwWrongArea>::iterator i = maList.begin();
540  if ( nWhere >= maList.size() )
541  i = maList.end(); // robust
542  else
543  i += nWhere;
544  maList.insert(i, startPos, endPos); // insert [startPos, endPos[ before i
545 
546  // ownership of the sublist is passed to maList, therefore we have to set the
547  // pSubList-Pointers to 0
548  while ( startPos != endPos )
549  {
550  (*startPos).mpSubList = nullptr;
551  ++startPos;
552  }
553 }
554 
555 void SwWrongList::Remove(sal_uInt16 nIdx, sal_uInt16 nLen )
556 {
557  if ( nIdx >= maList.size() ) return;
558  std::vector<SwWrongArea>::iterator i1 = maList.begin();
559  i1 += nIdx;
560 
561  std::vector<SwWrongArea>::iterator i2 = i1;
562  if ( nIdx + nLen >= static_cast<sal_uInt16>(maList.size()) )
563  i2 = maList.end(); // robust
564  else
565  i2 += nLen;
566 
567  std::vector<SwWrongArea>::iterator iLoop = i1;
568  while ( iLoop != i2 )
569  {
570  delete (*iLoop).mpSubList;
571  ++iLoop;
572  }
573 
574 #if OSL_DEBUG_LEVEL > 0
575  const int nOldSize = Count();
576 #endif
577 
578  maList.erase(i1, i2);
579 
580 #if OSL_DEBUG_LEVEL > 0
581  OSL_ENSURE( Count() + nLen == nOldSize, "SwWrongList::Remove() trouble" );
582 #endif
583 }
584 
585 void SwWrongList::RemoveEntry( sal_Int32 nBegin, sal_Int32 nEnd ) {
586  std::vector<SwWrongArea>::const_iterator aEnd(maList.end());
587  auto aDelIter = std::find_if(maList.cbegin(), aEnd,
588  [nBegin](const SwWrongArea& rST) { return rST.mnPos >= nBegin; });
589  auto aIter = aDelIter;
591  {
592  if( nBegin < nEnd )
593  {
594  aIter = std::find_if(aDelIter, aEnd,
595  [nEnd](const SwWrongArea& rST) { return rST.mnPos >= nEnd; });
596  }
597  }
598  else
599  {
600  aIter = std::find_if(aDelIter, aEnd,
601  [nBegin, nEnd](const SwWrongArea& rST) {
602  return (rST.mnPos != nBegin) || ((rST.mnPos + rST.mnLen) != nEnd);
603  });
604  }
605  auto nDel = static_cast<sal_uInt16>(std::distance(aDelIter, aIter));
606  if( nDel )
607  {
608  auto nDelPos = static_cast<sal_uInt16>(std::distance(maList.cbegin(), aDelIter));
609  Remove( nDelPos, nDel );
610  }
611 }
612 
613 bool SwWrongList::LookForEntry( sal_Int32 nBegin, sal_Int32 nEnd ) {
614  auto aIter = std::find_if(maList.begin(), maList.end(),
615  [nBegin](const SwWrongArea& rST) { return rST.mnPos >= nBegin; });
616  return aIter != maList.end()
617  && nBegin == (*aIter).mnPos
618  && nEnd == (*aIter).mnPos + (*aIter).mnLen;
619 }
620 
621 void SwWrongList::Insert( const OUString& rType,
622  css::uno::Reference< css::container::XStringKeyMap > const & xPropertyBag,
623  sal_Int32 nNewPos, sal_Int32 nNewLen )
624 {
625  auto aIter = std::find_if(maList.begin(), maList.end(),
626  [nNewPos](const SwWrongArea& rST) { return nNewPos <= rST.mnPos; });
627  if ( aIter != maList.end() && nNewPos == (*aIter).mnPos )
628  {
629  const sal_Int32 nSTPos = (*aIter).mnPos;
630 
631  aIter = std::find_if(aIter, maList.end(),
632  [nSTPos, nNewLen](const SwWrongArea& rST) { return rST.mnPos != nSTPos || nNewLen < rST.mnLen; });
633  }
634 
635  maList.insert(aIter, SwWrongArea( rType, meType, xPropertyBag, nNewPos, nNewLen) );
636 }
637 
638 namespace sw {
639 
641  SwWrongList const* (SwTextNode::*pGetWrongList)() const)
642  : m_pGetWrongList(pGetWrongList)
643  , m_pMergedPara(rFrame.GetMergedPara())
644  , m_CurrentExtent(0)
645  , m_CurrentIndex(0)
646  , m_pWrongList(m_pMergedPara
647  ? nullptr
648  : (rFrame.GetTextNodeFirst()->*pGetWrongList)())
649 {
650 }
651 
653  : m_pGetWrongList(nullptr)
654  , m_pMergedPara(nullptr)
655  , m_CurrentExtent(0)
656  , m_CurrentIndex(0)
657  , m_pWrongList(&rWrongList)
658 {
659 }
660 
662  SwWrongList const* (SwTextNode::*pGetWrongList)() const)
663  : WrongListIteratorBase(rFrame, pGetWrongList)
664 {
665 }
666 
668  : WrongListIteratorBase(rWrongList)
669 {
670 }
671 
673 {
674  if (m_pMergedPara)
675  {
676  if (rStart < m_CurrentIndex)
677  { // rewind
678  m_CurrentExtent = 0;
680  }
681  while (m_CurrentExtent < m_pMergedPara->extents.size())
682  {
684  if (rStart + rLen <= m_CurrentIndex)
685  {
686  return false;
687  }
688  else if (rStart < m_CurrentIndex)
689  {
690  rLen -= m_CurrentIndex - rStart;
691  assert(0 < sal_Int32(rLen));
692  rStart = m_CurrentIndex;
693  }
694  if (m_CurrentIndex <= rStart &&
695  rStart < m_CurrentIndex + TextFrameIndex(rExtent.nEnd - rExtent.nStart))
696  {
697  SwWrongList const*const pWrongList((rExtent.pNode->*m_pGetWrongList)());
698  // found the extent containing start - first, call Check
699  sal_Int32 nStart(rExtent.nStart + sal_Int32(rStart - m_CurrentIndex)); // (m_CurrentIndex - m_CurrentNodeIndex));
700  sal_Int32 nLen;
701  if (sal_Int32(rLen) < rExtent.nEnd - nStart)
702  {
703  nLen = sal_Int32(rLen);
704  }
705  else
706  {
707  sal_Int32 nInLen(rLen);
708  nLen = rExtent.nEnd - nStart;
709  nInLen -= nLen;
710  for (size_t i = m_CurrentExtent + 1;
711  i < m_pMergedPara->extents.size(); ++i)
712  {
713  sw::Extent const& rExtentEnd(m_pMergedPara->extents[i]);
714  if (rExtentEnd.pNode != rExtent.pNode)
715  {
716  nInLen = 0;
717  break;
718  }
719  // add gap too
720  nLen += rExtentEnd.nStart - m_pMergedPara->extents[i-1].nEnd;
721  if (nInLen <= rExtentEnd.nEnd - rExtentEnd.nStart)
722  {
723  nLen += nInLen;
724  nInLen = 0;
725  break;
726  }
727  nLen += rExtentEnd.nEnd - rExtentEnd.nStart;
728  nInLen -= rExtentEnd.nEnd - rExtentEnd.nStart;
729  }
730  }
731  if (pWrongList && pWrongList->Check(nStart, nLen))
732  {
733  // check if there's overlap with this extent
734  if (rExtent.nStart <= nStart && nStart < rExtent.nEnd)
735  {
736  // yes - now compute end position / length
737  sal_Int32 const nEnd(nStart + nLen);
738  rStart = m_CurrentIndex + TextFrameIndex(nStart - rExtent.nStart);
739  TextFrameIndex const nOrigLen(rLen);
740  if (nEnd <= rExtent.nEnd)
741  {
742  rLen = TextFrameIndex(nEnd - nStart);
743  }
744  else // have to search other extents for the end...
745  {
746  rLen = TextFrameIndex(rExtent.nEnd - nStart);
747  for (size_t i = m_CurrentExtent + 1;
748  i < m_pMergedPara->extents.size(); ++i)
749  {
750  sw::Extent const& rExtentEnd(m_pMergedPara->extents[i]);
751  if (rExtentEnd.pNode != rExtent.pNode
752  || nEnd <= rExtentEnd.nStart)
753  {
754  break;
755  }
756  if (nEnd <= rExtentEnd.nEnd)
757  {
758  rLen += TextFrameIndex(nEnd - rExtentEnd.nStart);
759  break;
760  }
761  rLen += TextFrameIndex(rExtentEnd.nEnd - rExtentEnd.nStart);
762  }
763  }
764  assert(rLen <= nOrigLen); (void) nOrigLen;
765  return true;
766  }
767  }
768  }
769  m_CurrentIndex += TextFrameIndex(rExtent.nEnd - rExtent.nStart);
770  ++m_CurrentExtent;
771  }
772  return false;
773  }
774  else if (m_pWrongList)
775  {
776  sal_Int32 nStart(rStart);
777  sal_Int32 nLen(rLen);
778  bool const bRet(m_pWrongList->Check(nStart, nLen));
779  rStart = TextFrameIndex(nStart);
780  rLen = TextFrameIndex(nLen);
781  return bRet;
782  }
783  return false;
784 }
785 
786 const SwWrongArea*
788 {
789  if (m_pMergedPara)
790  {
791  if (nStart < m_CurrentIndex)
792  { // rewind
793  m_CurrentExtent = 0;
795  }
796  while (m_CurrentExtent < m_pMergedPara->extents.size())
797  {
799  if (m_CurrentIndex <= nStart &&
800  nStart <= m_CurrentIndex + TextFrameIndex(rExtent.nEnd - rExtent.nStart))
801  {
802  // note: the returned object isn't wrapped because fntcache.cxx
803  // does not look at its positions, only its formatting props
804  SwWrongList const*const pWrongList((rExtent.pNode->*m_pGetWrongList)());
805  if (pWrongList)
806  {
807  sal_Int32 const nNStart(rExtent.nStart + sal_Int32(nStart - m_CurrentIndex)); // (m_CurrentIndex - m_CurrentNodeIndex));
808  sal_Int16 const nPos(pWrongList->GetWrongPos(nNStart));
809  return pWrongList->GetElement(nPos);
810  }
811  }
812  m_CurrentIndex += TextFrameIndex(rExtent.nEnd - rExtent.nStart);
813  ++m_CurrentExtent;
814  }
815  return nullptr;
816  }
817  else if (m_pWrongList)
818  {
819  sal_Int16 const nPos(m_pWrongList->GetWrongPos(sal_Int32(nStart)));
820  return m_pWrongList->GetElement(nPos);
821  }
822  return nullptr;
823 }
824 
826  SwWrongList const* (SwTextNode::*pGetWrongList)() const)
827  : WrongListIteratorBase(rFrame, pGetWrongList)
828 {
829 }
830 
832  : WrongListIteratorBase(rWrongList)
833 {
834 }
835 
837 {
838  if (m_pMergedPara)
839  {
840  sal_uInt16 nRet(0);
841  m_CurrentExtent = 0;
843  SwNode const* pNode(nullptr);
844  sal_uInt16 InCurrentNode(0);
845  while (m_CurrentExtent < m_pMergedPara->extents.size())
846  {
848  if (rExtent.pNode != pNode)
849  {
850  InCurrentNode = 0;
851  pNode = rExtent.pNode;
852  }
853  SwWrongList const*const pWrongList((rExtent.pNode->*m_pGetWrongList)());
854  for (; pWrongList && InCurrentNode < pWrongList->Count(); ++InCurrentNode)
855  {
856  SwWrongArea const*const pWrong(pWrongList->GetElement(InCurrentNode));
857  TextFrameIndex const nExtentEnd(
858  m_CurrentIndex + TextFrameIndex(rExtent.nEnd - rExtent.nStart));
859  if (nExtentEnd <= TextFrameIndex(pWrong->mnPos))
860  {
861  break; // continue outer loop
862  }
863  if (m_CurrentIndex < TextFrameIndex(pWrong->mnPos + pWrong->mnLen))
864  {
865  ++nRet;
866  }
867  }
868  m_CurrentIndex += TextFrameIndex(rExtent.nEnd - rExtent.nStart);
869  ++m_CurrentExtent;
870  }
871  return nRet;
872  }
873  else if (m_pWrongList)
874  {
875  return m_pWrongList->Count();
876  }
877  return 0;
878 }
879 
882 {
883  if (m_pMergedPara)
884  {
885  m_CurrentExtent = 0;
887  SwNode const* pNode(nullptr);
888  sal_uInt16 InCurrentNode(0);
889  while (m_CurrentExtent < m_pMergedPara->extents.size())
890  {
892  if (rExtent.pNode != pNode)
893  {
894  InCurrentNode = 0;
895  pNode = rExtent.pNode;
896  }
897  SwWrongList const*const pWrongList((rExtent.pNode->*m_pGetWrongList)());
898  for (; pWrongList && InCurrentNode < pWrongList->Count(); ++InCurrentNode)
899  {
900  SwWrongArea const*const pWrong(pWrongList->GetElement(InCurrentNode));
901  TextFrameIndex const nExtentEnd(
902  m_CurrentIndex + TextFrameIndex(rExtent.nEnd - rExtent.nStart));
903  if (nExtentEnd <= TextFrameIndex(pWrong->mnPos))
904  {
905  break; // continue outer loop
906  }
907  if (m_CurrentIndex < TextFrameIndex(pWrong->mnPos + pWrong->mnLen))
908  {
909  if (nIndex == 0)
910  {
912  std::pair<TextFrameIndex, TextFrameIndex>(
914  std::max(rExtent.nStart, pWrong->mnPos)),
916  std::min(pWrong->mnPos + pWrong->mnLen, rExtent.nEnd))));
917  }
918  --nIndex;
919  }
920  }
921  m_CurrentIndex += TextFrameIndex(rExtent.nEnd - rExtent.nStart);
922  ++m_CurrentExtent;
923  }
925  }
926  else if (m_pWrongList)
927  {
928  SwWrongArea const*const pWrong(m_pWrongList->GetElement(nIndex));
930  std::pair<TextFrameIndex, TextFrameIndex>(
931  TextFrameIndex(pWrong->mnPos),
932  TextFrameIndex(pWrong->mnPos + pWrong->mnLen)));
933  }
935 }
936 
937 } // namespace sw
938 
939 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int32 mnBeginInvalid
Definition: wrong.hxx:271
sal_Int32 Pos(sal_uInt16 nIdx) const
Definition: wrong.hxx:322
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:149
OUString maType
bool InvalidateWrong()
Definition: wrong.cxx:433
WrongListType
Definition: wrong.hxx:57
const SwWrongArea * GetWrongElement(TextFrameIndex nStart)
Definition: wrong.cxx:787
void Invalidate_(sal_Int32 nBegin, sal_Int32 nEnd)
Definition: wrong.cxx:245
PrimitiveType meType
FreshState Fresh(sal_Int32 &rStart, sal_Int32 &rEnd, sal_Int32 nPos, sal_Int32 nLen, sal_uInt16 nIndex, sal_Int32 nCursorPos)
Remove given range of entries.
Definition: wrong.cxx:355
void Move(sal_Int32 nPos, sal_Int32 nDiff)
Change all values after the given position.
Definition: wrong.cxx:266
SwWrongList const *const m_pWrongList
Definition: wrong.hxx:375
void InsertSubList(sal_Int32 nNewPos, sal_Int32 nNewLen, sal_uInt16 nWhere, SwWrongList *pSubList)
Definition: wrong.cxx:522
WrongAreaLineType mLineType
Definition: wrong.hxx:75
Dialog to specify the properties of date form field.
Definition: accfrmobj.cxx:40
static WrongAreaLineType getWrongAreaLineType(WrongListType listType, css::uno::Reference< css::container::XStringKeyMap > const &xPropertyBag)
Definition: wrong.hxx:245
WrongListIteratorBase(SwTextFrame const &rFrame, SwWrongList const *(SwTextNode::*pGetWrongList)() const)
for the text frame
Definition: wrong.cxx:640
void RemoveEntry(sal_Int32 nBegin, sal_Int32 nEnd)
Definition: wrong.cxx:585
SwTextNode * pNode
Definition: txtfrm.hxx:85
Color mColor
Definition: wrong.hxx:74
sal_Int32 nEnd
Definition: txtfrm.hxx:87
virtual void CopyFrom(const SwWrongList &rCopy)
Definition: wrong.cxx:72
void Remove(sal_uInt16 nIdx, sal_uInt16 nLen)
Definition: wrong.cxx:555
void JoinList(SwWrongList *pNext, sal_Int32 nInsertPos)
Definition: wrong.cxx:489
std::vector< Extent > extents
Definition: txtfrm.hxx:957
virtual SwWrongList * Clone()
Definition: wrong.cxx:65
Describes a part of a single text node, which will be part of a text frame, even when redlines are hi...
Definition: txtfrm.hxx:83
sal_Int32 NextWrong(sal_Int32 nChk) const
Find next incorrectly selected position.
Definition: wrong.cxx:163
static Color getWrongAreaColor(WrongListType listType, css::uno::Reference< css::container::XStringKeyMap > const &xPropertyBag)
Definition: wrong.hxx:226
SwWrongList const *(SwTextNode::*const m_pGetWrongList)() const
Definition: wrong.hxx:371
sal_uInt16 Count() const
Definition: wrong.hxx:327
SwWrongList * SplitList(sal_Int32 nSplitPos)
Definition: wrong.cxx:445
virtual ~SwWrongList()
Definition: wrong.cxx:60
sw::MergedPara const *const m_pMergedPara
Definition: wrong.hxx:372
sal_Int32 mnLen
Definition: wrong.hxx:71
Count
int i
sal_Int32 Len(sal_uInt16 nIdx) const
Definition: wrong.hxx:317
bool LookForEntry(sal_Int32 nBegin, sal_Int32 nEnd)
Definition: wrong.cxx:613
void Invalidate(sal_Int32 nBegin, sal_Int32 nEnd)
Definition: wrong.cxx:425
bool Check(sal_Int32 &rChk, sal_Int32 &rLn) const
Calculate first incorrectly selected area.
Definition: wrong.cxx:126
sal_Int32 GetEndInv() const
Definition: wrong.hxx:293
WrongListIteratorCounter(SwTextFrame const &rFrame, SwWrongList const *(SwTextNode::*pGetWrongList)() const)
Definition: wrong.cxx:825
bool Check(TextFrameIndex &rStart, TextFrameIndex &rLen)
Definition: wrong.cxx:672
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
boost::optional< std::pair< TextFrameIndex, TextFrameIndex > > GetElementAt(sal_uInt16 nIndex)
Definition: wrong.cxx:881
WrongListType GetWrongListType() const
Definition: wrong.hxx:291
sal_Int32 GetBeginInv() const
Definition: wrong.hxx:292
WrongListIterator(SwTextFrame const &rFrame, SwWrongList const *(SwTextNode::*pGetWrongList)() const)
for the text frame
Definition: wrong.cxx:661
sal_uInt16 GetWrongPos(sal_Int32 nValue) const
Find the first position that is greater or equal to the given value.
Definition: wrong.cxx:190
void ClearList()
Definition: wrong.cxx:85
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 void ShiftLeft(sal_Int32 &rPos, sal_Int32 nStart, sal_Int32 nEnd)
Definition: wrong.hxx:274
const SwWrongArea * GetElement(sal_uInt16 nIdx) const
Definition: wrong.hxx:353
sal_Int32 nStart
Definition: txtfrm.hxx:86
SwWrongList(const SwWrongList &rCpy)=delete
sal_Int32 mnPos
Definition: wrong.hxx:70
WrongListType meType
Definition: wrong.hxx:269
sal_uInt16 GetElementCount()
Definition: wrong.cxx:836
SwWrongArea(const OUString &rType, WrongListType listType, css::uno::Reference< css::container::XStringKeyMap > const &xPropertyBag, sal_Int32 nPos, sal_Int32 nLen)
Definition: wrong.cxx:28
std::vector< SwWrongArea > maList
Definition: wrong.hxx:268
TextFrameIndex m_CurrentIndex
Definition: wrong.hxx:374
void Insert(sal_uInt16 nWhere, std::vector< SwWrongArea >::iterator startPos, std::vector< SwWrongArea >::iterator const &endPos)
Definition: wrong.cxx:537
sal_Int32 nPos
o3tl::strong_int< sal_Int32, struct Tag_TextFrameIndex > TextFrameIndex
Denotes a character index in a text frame at a layout level, after extent mapping from a text node at...
sal_Int32 mnEndInvalid
Definition: wrong.hxx:272
const sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:61
void SetInvalid(sal_Int32 nBegin, sal_Int32 nEnd)
Definition: wrong.cxx:253
Base class of the Writer document model elements.
Definition: node.hxx:79
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo