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
28SwWrongArea::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), mxPropertyBag(xPropertyBag), mnPos(nPos), mnLen(nLen), mpSubList(nullptr)
33{
34 mColor = getWrongAreaColor(listType, xPropertyBag);
35 mLineType = getWrongAreaLineType(listType, xPropertyBag);
36}
37
38SwWrongArea::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), mxPropertyBag(xPropertyBag), 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
73{
74 maList = rCopy.maList;
75 meType = rCopy.meType;
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
102bool 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
126bool 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
163sal_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
190sal_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 o3tl::narrowing<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
245void 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
253void SwWrongList::SetInvalid( sal_Int32 nBegin, sal_Int32 nEnd )
254{
255 mnBeginInvalid = nBegin;
256 mnEndInvalid = nEnd;
257}
258
266void 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;
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;
311 {
312 if( mnBeginInvalid > nPos )
313 mnBeginInvalid += nDiff;
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
355auto 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
425void SwWrongList::Invalidate( sal_Int32 nBegin, sal_Int32 nEnd )
426{
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
445std::unique_ptr<SwWrongList> SwWrongList::SplitList( sal_Int32 nSplitPos )
446{
447 std::unique_ptr<SwWrongList> pRet;
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.reset(new SwGrammarMarkUp());
466 else
467 pRet.reset(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 }
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
489void 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
522void 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
537void 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
555void 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 >= o3tl::narrowing<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
585void 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 = o3tl::narrowing<sal_uInt16>(std::distance(aDelIter, aIter));
606 if( nDel )
607 {
608 auto nDelPos = o3tl::narrowing<sal_uInt16>(std::distance(maList.cbegin(), aDelIter));
609 Remove( nDelPos, nDel );
610 }
611}
612
613bool 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
621void 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
638namespace 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 break;
717 }
718 // add gap too
719 nLen += rExtentEnd.nStart - m_pMergedPara->extents[i-1].nEnd;
720 if (nInLen <= rExtentEnd.nEnd - rExtentEnd.nStart)
721 {
722 nLen += nInLen;
723 break;
724 }
725 nLen += rExtentEnd.nEnd - rExtentEnd.nStart;
726 nInLen -= rExtentEnd.nEnd - rExtentEnd.nStart;
727 }
728 }
729 if (pWrongList && pWrongList->Check(nStart, nLen))
730 {
731 // check if there's overlap with this extent
732 if (rExtent.nStart <= nStart && nStart < rExtent.nEnd)
733 {
734 // yes - now compute end position / length
735 sal_Int32 const nEnd(nStart + nLen);
736 rStart = m_CurrentIndex + TextFrameIndex(nStart - rExtent.nStart);
737 TextFrameIndex const nOrigLen(rLen);
738 if (nEnd <= rExtent.nEnd)
739 {
740 rLen = TextFrameIndex(nEnd - nStart);
741 }
742 else // have to search other extents for the end...
743 {
744 rLen = TextFrameIndex(rExtent.nEnd - nStart);
745 for (size_t i = m_CurrentExtent + 1;
746 i < m_pMergedPara->extents.size(); ++i)
747 {
748 sw::Extent const& rExtentEnd(m_pMergedPara->extents[i]);
749 if (rExtentEnd.pNode != rExtent.pNode
750 || nEnd <= rExtentEnd.nStart)
751 {
752 break;
753 }
754 if (nEnd <= rExtentEnd.nEnd)
755 {
756 rLen += TextFrameIndex(nEnd - rExtentEnd.nStart);
757 break;
758 }
759 rLen += TextFrameIndex(rExtentEnd.nEnd - rExtentEnd.nStart);
760 }
761 }
762 assert(rLen <= nOrigLen); (void) nOrigLen;
763 return true;
764 }
765 }
766 }
767 m_CurrentIndex += TextFrameIndex(rExtent.nEnd - rExtent.nStart);
769 }
770 return false;
771 }
772 else if (m_pWrongList)
773 {
774 sal_Int32 nStart(rStart);
775 sal_Int32 nLen(rLen);
776 bool const bRet(m_pWrongList->Check(nStart, nLen));
777 rStart = TextFrameIndex(nStart);
778 rLen = TextFrameIndex(nLen);
779 return bRet;
780 }
781 return false;
782}
783
784const SwWrongArea*
786{
787 if (m_pMergedPara)
788 {
789 if (nStart < m_CurrentIndex)
790 { // rewind
791 m_CurrentExtent = 0;
793 }
794 while (m_CurrentExtent < m_pMergedPara->extents.size())
795 {
797 if (m_CurrentIndex <= nStart &&
798 nStart <= m_CurrentIndex + TextFrameIndex(rExtent.nEnd - rExtent.nStart))
799 {
800 // note: the returned object isn't wrapped because fntcache.cxx
801 // does not look at its positions, only its formatting props
802 SwWrongList const*const pWrongList((rExtent.pNode->*m_pGetWrongList)());
803 if (pWrongList)
804 {
805 sal_Int32 const nNStart(rExtent.nStart + sal_Int32(nStart - m_CurrentIndex)); // (m_CurrentIndex - m_CurrentNodeIndex));
806 sal_Int16 const nPos(pWrongList->GetWrongPos(nNStart));
807 return pWrongList->GetElement(nPos);
808 }
809 }
810 m_CurrentIndex += TextFrameIndex(rExtent.nEnd - rExtent.nStart);
812 }
813 return nullptr;
814 }
815 else if (m_pWrongList)
816 {
817 sal_Int16 const nPos(m_pWrongList->GetWrongPos(sal_Int32(nStart)));
819 }
820 return nullptr;
821}
822
824 SwWrongList const* (SwTextNode::*pGetWrongList)() const)
825 : WrongListIteratorBase(rFrame, pGetWrongList)
826{
827}
828
830 : WrongListIteratorBase(rWrongList)
831{
832}
833
835{
836 if (m_pMergedPara)
837 {
838 sal_uInt16 nRet(0);
839 m_CurrentExtent = 0;
841 SwNode const* pNode(nullptr);
842 sal_uInt16 InCurrentNode(0);
843 while (m_CurrentExtent < m_pMergedPara->extents.size())
844 {
846 if (rExtent.pNode != pNode)
847 {
848 InCurrentNode = 0;
849 pNode = rExtent.pNode;
850 }
851 SwWrongList const*const pWrongList((rExtent.pNode->*m_pGetWrongList)());
852 for (; pWrongList && InCurrentNode < pWrongList->Count(); ++InCurrentNode)
853 {
854 SwWrongArea const*const pWrong(pWrongList->GetElement(InCurrentNode));
855 TextFrameIndex const nExtentEnd(
856 m_CurrentIndex + TextFrameIndex(rExtent.nEnd - rExtent.nStart));
857 if (nExtentEnd <= TextFrameIndex(pWrong->mnPos))
858 {
859 break; // continue outer loop
860 }
861 if (m_CurrentIndex < TextFrameIndex(pWrong->mnPos + pWrong->mnLen))
862 {
863 ++nRet;
864 }
865 }
866 m_CurrentIndex += TextFrameIndex(rExtent.nEnd - rExtent.nStart);
868 }
869 return nRet;
870 }
871 else if (m_pWrongList)
872 {
873 return m_pWrongList->Count();
874 }
875 return 0;
876}
877
878std::optional<std::pair<TextFrameIndex, TextFrameIndex>>
880{
881 if (m_pMergedPara)
882 {
883 m_CurrentExtent = 0;
885 SwNode const* pNode(nullptr);
886 sal_uInt16 InCurrentNode(0);
887 while (m_CurrentExtent < m_pMergedPara->extents.size())
888 {
890 if (rExtent.pNode != pNode)
891 {
892 InCurrentNode = 0;
893 pNode = rExtent.pNode;
894 }
895 SwWrongList const*const pWrongList((rExtent.pNode->*m_pGetWrongList)());
896 for (; pWrongList && InCurrentNode < pWrongList->Count(); ++InCurrentNode)
897 {
898 SwWrongArea const*const pWrong(pWrongList->GetElement(InCurrentNode));
899 TextFrameIndex const nExtentEnd(
900 m_CurrentIndex + TextFrameIndex(rExtent.nEnd - rExtent.nStart));
901 if (nExtentEnd <= TextFrameIndex(pWrong->mnPos))
902 {
903 break; // continue outer loop
904 }
905 if (m_CurrentIndex < TextFrameIndex(pWrong->mnPos + pWrong->mnLen))
906 {
907 if (nIndex == 0)
908 {
909 return std::optional<std::pair<TextFrameIndex, TextFrameIndex>>(
910 std::pair<TextFrameIndex, TextFrameIndex>(
912 std::max(rExtent.nStart, pWrong->mnPos)),
914 std::min(pWrong->mnPos + pWrong->mnLen, rExtent.nEnd))));
915 }
916 --nIndex;
917 }
918 }
919 m_CurrentIndex += TextFrameIndex(rExtent.nEnd - rExtent.nStart);
921 }
922 return std::optional<std::pair<TextFrameIndex, TextFrameIndex>>();
923 }
924 else if (m_pWrongList)
925 {
926 SwWrongArea const*const pWrong(m_pWrongList->GetElement(nIndex));
927 return std::optional<std::pair<TextFrameIndex, TextFrameIndex>>(
928 std::pair<TextFrameIndex, TextFrameIndex>(
929 TextFrameIndex(pWrong->mnPos),
930 TextFrameIndex(pWrong->mnPos + pWrong->mnLen)));
931 }
932 return std::optional<std::pair<TextFrameIndex, TextFrameIndex>>();
933}
934
935} // namespace sw
936
937/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
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...
Base class of the Writer document model elements.
Definition: node.hxx:83
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:163
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:84
Color mColor
Definition: wrong.hxx:74
sal_Int32 mnPos
Definition: wrong.hxx:70
static Color getWrongAreaColor(WrongListType listType, css::uno::Reference< css::container::XStringKeyMap > const &xPropertyBag)
Definition: wrong.hxx:222
WrongAreaLineType mLineType
Definition: wrong.hxx:75
SwWrongArea(const OUString &rType, WrongListType listType, css::uno::Reference< css::container::XStringKeyMap > const &xPropertyBag, sal_Int32 nPos, sal_Int32 nLen)
Definition: wrong.cxx:28
sal_Int32 mnLen
Definition: wrong.hxx:71
static WrongAreaLineType getWrongAreaLineType(WrongListType listType, css::uno::Reference< css::container::XStringKeyMap > const &xPropertyBag)
Definition: wrong.hxx:241
void ClearList()
Definition: wrong.cxx:85
bool InvalidateWrong()
Definition: wrong.cxx:433
sal_uInt16 Count() const
Definition: wrong.hxx:323
sal_Int32 GetEndInv() const
Definition: wrong.hxx:289
void RemoveEntry(sal_Int32 nBegin, sal_Int32 nEnd)
Definition: wrong.cxx:585
std::unique_ptr< SwWrongList > SplitList(sal_Int32 nSplitPos)
Definition: wrong.cxx:445
WrongListType GetWrongListType() const
Definition: wrong.hxx:287
void JoinList(SwWrongList *pNext, sal_Int32 nInsertPos)
Definition: wrong.cxx:489
const SwWrongArea * GetElement(sal_uInt16 nIdx) const
Definition: wrong.hxx:349
bool Check(sal_Int32 &rChk, sal_Int32 &rLn) const
Calculate first incorrectly selected area.
Definition: wrong.cxx:126
virtual SwWrongList * Clone()
Definition: wrong.cxx:65
void Invalidate(sal_Int32 nBegin, sal_Int32 nEnd)
Definition: wrong.cxx:425
std::vector< SwWrongArea > maList
Definition: wrong.hxx:264
sal_Int32 mnEndInvalid
Definition: wrong.hxx:268
sal_Int32 Pos(sal_uInt16 nIdx) const
Definition: wrong.hxx:318
void InsertSubList(sal_Int32 nNewPos, sal_Int32 nNewLen, sal_uInt16 nWhere, SwWrongList *pSubList)
Definition: wrong.cxx:522
SwWrongList(const SwWrongList &rCpy)=delete
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
virtual void CopyFrom(const SwWrongList &rCopy)
Definition: wrong.cxx:72
sal_uInt16 GetWrongPos(sal_Int32 nValue) const
Find the first position that is greater or equal to the given value.
Definition: wrong.cxx:190
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
void Invalidate_(sal_Int32 nBegin, sal_Int32 nEnd)
Definition: wrong.cxx:245
void Remove(sal_uInt16 nIdx, sal_uInt16 nLen)
Definition: wrong.cxx:555
void SetInvalid(sal_Int32 nBegin, sal_Int32 nEnd)
Definition: wrong.cxx:253
static void ShiftLeft(sal_Int32 &rPos, sal_Int32 nStart, sal_Int32 nEnd)
Definition: wrong.hxx:270
void Move(sal_Int32 nPos, sal_Int32 nDiff)
Change all values after the given position.
Definition: wrong.cxx:266
void Insert(sal_uInt16 nWhere, std::vector< SwWrongArea >::iterator startPos, std::vector< SwWrongArea >::iterator const &endPos)
Definition: wrong.cxx:537
sal_Int32 GetBeginInv() const
Definition: wrong.hxx:288
virtual ~SwWrongList()
Definition: wrong.cxx:60
WrongListType meType
Definition: wrong.hxx:265
bool LookForEntry(sal_Int32 nBegin, sal_Int32 nEnd)
Definition: wrong.cxx:613
sal_Int32 mnBeginInvalid
Definition: wrong.hxx:267
sal_Int32 Len(sal_uInt16 nIdx) const
Definition: wrong.hxx:313
sal_Int32 NextWrong(sal_Int32 nChk) const
Find next incorrectly selected position.
Definition: wrong.cxx:163
sw::MergedPara const *const m_pMergedPara
Definition: wrong.hxx:368
SwWrongList const *(SwTextNode::*const m_pGetWrongList)() const
Definition: wrong.hxx:367
WrongListIteratorBase(SwTextFrame const &rFrame, SwWrongList const *(SwTextNode::*pGetWrongList)() const)
for the text frame
Definition: wrong.cxx:640
SwWrongList const *const m_pWrongList
Definition: wrong.hxx:371
TextFrameIndex m_CurrentIndex
Definition: wrong.hxx:370
sal_uInt16 GetElementCount()
Definition: wrong.cxx:834
std::optional< std::pair< TextFrameIndex, TextFrameIndex > > GetElementAt(sal_uInt16 nIndex)
Definition: wrong.cxx:879
WrongListIteratorCounter(SwTextFrame const &rFrame, SwWrongList const *(SwTextNode::*pGetWrongList)() const)
Definition: wrong.cxx:823
bool Check(TextFrameIndex &rStart, TextFrameIndex &rLen)
Definition: wrong.cxx:672
WrongListIterator(SwTextFrame const &rFrame, SwWrongList const *(SwTextNode::*pGetWrongList)() const)
for the text frame
Definition: wrong.cxx:661
const SwWrongArea * GetWrongElement(TextFrameIndex nStart)
Definition: wrong.cxx:785
DocumentType eType
sal_Int16 nValue
sal_Int32 nIndex
sal_uInt16 nPos
int i
Count
Dialog to specify the properties of date form field.
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
Describes a part of a single text node, which will be part of a text frame, even when redlines are hi...
Definition: txtfrm.hxx:87
sal_Int32 nEnd
Definition: txtfrm.hxx:90
sal_Int32 nStart
Definition: txtfrm.hxx:89
SwTextNode * pNode
Definition: txtfrm.hxx:88
std::vector< Extent > extents
Definition: txtfrm.hxx:963
constexpr sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:57
OUString maType
RedlineType meType
WrongListType
Definition: wrong.hxx:57
@ WRONGLIST_GRAMMAR
Definition: wrong.hxx:59
@ WRONGAREA_NONE
Definition: wrong.hxx:49