update dev300-m58
[ooovba.git] / sw / source / core / text / wrong.cxx
blob7888802984709cbb6094cebf943f811035b9377e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: wrong.cxx,v $
10 * $Revision: 1.16 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <tools/string.hxx>
36 #include <tools/debug.hxx>
37 #include "errhdl.hxx"
38 #include "swtypes.hxx"
39 #include "txttypes.hxx"
41 #include "SwGrammarMarkUp.hxx"
44 /*************************************************************************
45 * SwWrongList::SwWrongList()
46 *************************************************************************/
47 SwWrongList::SwWrongList( WrongListType eType ) :
48 meType (eType),
49 nBeginInvalid(STRING_LEN), // everything correct... (the invalid area starts beyond the string)
50 nEndInvalid (STRING_LEN)
52 maList.reserve( 5 );
55 SwWrongList::~SwWrongList()
57 ClearList();
60 /*************************************************************************
61 * SwWrongList* SwWrongList::Clone()
62 *************************************************************************/
64 SwWrongList* SwWrongList::Clone()
66 SwWrongList* pClone = new SwWrongList( meType );
67 pClone->CopyFrom( *this );
68 return pClone;
71 /*************************************************************************
72 * void SwWrongList::CopyFrom( const SwWrongList& rCopy )
73 *************************************************************************/
75 void SwWrongList::CopyFrom( const SwWrongList& rCopy )
77 maList = rCopy.maList;
78 meType = rCopy.meType;
79 nBeginInvalid = rCopy.nBeginInvalid;
80 nEndInvalid = rCopy.nEndInvalid;
81 for( size_t i = 0; i < maList.size(); ++i )
83 if( maList[i].mpSubList )
84 maList[i].mpSubList = maList[i].mpSubList->Clone();
88 /*************************************************************************
89 * SwWrongList::ClearList()
90 *************************************************************************/
91 void SwWrongList::ClearList()
93 for ( size_t i = 0; i < maList.size(); ++i)
95 if (maList[i].mpSubList)
96 delete maList[i].mpSubList;
97 maList[i].mpSubList = NULL;
99 maList.clear();
102 /*************************************************************************
103 * sal_Bool SwWrongList::InWrongWord() gibt den Anfang und die Laenge des
104 * Wortes zurueck, wenn es als falsch markiert ist.
105 *************************************************************************/
106 sal_Bool SwWrongList::InWrongWord( xub_StrLen &rChk, xub_StrLen &rLn ) const
108 MSHORT nPos = GetWrongPos( rChk );
109 xub_StrLen nWrPos;
110 if( nPos < Count() && ( nWrPos = Pos( nPos ) ) <= rChk )
112 rLn = Len( nPos );
113 if( nWrPos + rLn <= rChk )
114 return sal_False;
115 rChk = nWrPos;
116 return sal_True;
118 return sal_False;
121 /*************************************************************************
122 * sal_Bool SwWrongList::Check() liefert den ersten falschen Bereich
123 *************************************************************************/
124 sal_Bool SwWrongList::Check( xub_StrLen &rChk, xub_StrLen &rLn ) const
126 MSHORT nPos = GetWrongPos( rChk );
127 rLn = rLn + rChk;
128 xub_StrLen nWrPos;
130 if( nPos == Count() )
131 return sal_False;
133 xub_StrLen nEnd = Len( nPos );
134 nEnd = nEnd + ( nWrPos = Pos( nPos ) );
135 if( nEnd == rChk )
137 ++nPos;
138 if( nPos == Count() )
139 return sal_False;
140 else
142 nEnd = Len( nPos );
143 nEnd = nEnd + ( nWrPos = Pos( nPos ) );
146 if( nEnd > rChk && nWrPos < rLn )
148 if( nWrPos > rChk )
149 rChk = nWrPos;
150 if( nEnd < rLn )
151 rLn = nEnd;
152 rLn = rLn - rChk;
153 return 0 != rLn;
155 return sal_False;
158 /*************************************************************************
159 * xub_StrLen SwWrongList::NextWrong() liefert die naechste Fehlerposition
160 *************************************************************************/
162 xub_StrLen SwWrongList::NextWrong( xub_StrLen nChk ) const
164 xub_StrLen nRet;
165 xub_StrLen nPos = GetWrongPos( nChk );
166 if( nPos < Count() )
168 nRet = Pos( nPos );
169 if( nRet < nChk && nRet + Len( nPos ) <= nChk )
171 if( ++nPos < Count() )
172 nRet = Pos( nPos );
173 else
174 nRet = STRING_LEN;
177 else
178 nRet = STRING_LEN;
179 if( nRet > GetBeginInv() && nChk < GetEndInv() )
180 nRet = nChk > GetBeginInv() ? nChk : GetBeginInv();
181 return nRet;
184 /*************************************************************************
185 * MSHORT SwWrongList::GetWrongPos( xub_StrLen nValue )
186 * sucht die erste Position im Array, die groessergleich nValue ist,
187 * dies kann natuerlich auch hinter dem letzten Element sein!
188 *************************************************************************/
190 MSHORT SwWrongList::GetWrongPos( xub_StrLen nValue ) const
192 MSHORT nOben = Count(), nMitte = 0, nUnten = 0;
194 if( nOben > 0 )
196 // For smart tag lists, we may not use a binary search. We return the
197 // position of the first smart tag which coveres nValue
198 if ( 0 != maList[0].maType.getLength() || maList[0].mpSubList )
200 std::vector<SwWrongArea>::const_iterator aIter = maList.begin();
201 while ( aIter != maList.end() )
203 const xub_StrLen nSTPos = (*aIter).mnPos;
204 const xub_StrLen nSTLen = (*aIter).mnLen;
205 if ( nSTPos <= nValue && nValue < nSTPos + nSTLen )
206 break;
207 else if ( nSTPos > nValue )
208 break;
210 ++aIter;
211 ++nUnten;
213 return nUnten;
216 --nOben;
217 while( nUnten <= nOben )
219 nMitte = nUnten + ( nOben - nUnten ) / 2;
220 xub_StrLen nTmp = Pos( nMitte );
221 if( nTmp == nValue )
223 nUnten = nMitte;
224 break;
226 else if( nTmp < nValue )
228 if( nTmp + Len( nMitte ) >= nValue )
230 nUnten = nMitte;
231 break;
233 nUnten = nMitte + 1;
235 else if( nMitte == 0 )
237 break;
239 else
240 nOben = nMitte - 1;
244 // nUnten now points to an index i into the wrong list which
245 // 1. nValue is inside [ Area[i].pos, Area[i].pos + Area[i].len ] (inkl!!!)
246 // 2. nValue < Area[i].pos
248 return nUnten;
251 /*************************************************************************
252 * void SwWrongList::_Invalidate()
253 *************************************************************************/
255 void SwWrongList::_Invalidate( xub_StrLen nBegin, xub_StrLen nEnd )
257 if ( nBegin < GetBeginInv() )
258 nBeginInvalid = nBegin;
259 if ( nEnd > GetEndInv() )
260 nEndInvalid = nEnd;
263 void SwWrongList::SetInvalid( xub_StrLen nBegin, xub_StrLen nEnd )
265 nBeginInvalid = nBegin;
266 nEndInvalid = nEnd;
270 /*************************************************************************
271 * SwWrongList::Move( xub_StrLen nPos, long nDiff )
272 * veraendert alle Positionen ab nPos um den angegebenen Wert,
273 * wird nach Einfuegen oder Loeschen von Buchstaben benoetigt.
274 *************************************************************************/
276 void SwWrongList::Move( xub_StrLen nPos, long nDiff )
278 MSHORT i = GetWrongPos( nPos );
279 if( nDiff < 0 )
281 xub_StrLen nEnd = nPos + xub_StrLen( -nDiff );
282 MSHORT nLst = i;
283 xub_StrLen nWrPos;
284 xub_StrLen nWrLen;
285 sal_Bool bJump = sal_False;
286 while( nLst < Count() && Pos( nLst ) < nEnd )
287 ++nLst;
288 if( nLst > i && ( nWrPos = Pos( nLst - 1 ) ) <= nPos )
290 nWrLen = Len( nLst - 1 );
291 // calculate new length of word
292 nWrLen = ( nEnd > nWrPos + nWrLen ) ?
293 nPos - nWrPos :
294 static_cast<xub_StrLen>(nWrLen + nDiff);
295 if( nWrLen )
297 maList[--nLst].mnLen = nWrLen;
298 bJump = sal_True;
301 Remove( i, nLst - i );
303 if ( bJump )
304 ++i;
305 if( STRING_LEN == GetBeginInv() )
306 SetInvalid( nPos ? nPos - 1 : nPos, nPos + 1 );
307 else
309 ShiftLeft( nBeginInvalid, nPos, nEnd );
310 ShiftLeft( nEndInvalid, nPos, nEnd );
311 _Invalidate( nPos ? nPos - 1 : nPos, nPos + 1 );
314 else
316 xub_StrLen nWrPos;
317 xub_StrLen nEnd = nPos + xub_StrLen( nDiff );
318 if( STRING_LEN != GetBeginInv() )
320 if( nBeginInvalid > nPos )
321 nBeginInvalid = nBeginInvalid + xub_StrLen( nDiff );
322 if( nEndInvalid >= nPos )
323 nEndInvalid = nEndInvalid + xub_StrLen( nDiff );
325 // Wenn wir mitten in einem falschen Wort stehen, muss vom Wortanfang
326 // invalidiert werden.
327 if( i < Count() && nPos >= ( nWrPos = Pos( i ) ) )
329 Invalidate( nWrPos, nEnd );
330 xub_StrLen nWrLen = Len( i ) + xub_StrLen( nDiff );
331 maList[i++].mnLen = nWrLen;
332 nWrLen = nWrLen + nWrPos;
333 Invalidate( nWrPos, nWrLen );
335 else
336 Invalidate( nPos, nEnd );
338 while( i < Count() )
340 const xub_StrLen nTmp = static_cast<xub_StrLen>(nDiff + maList[i].mnPos);
341 maList[i++].mnPos = nTmp;
345 /*************************************************************************
346 * SwWrongList::Fresh
348 * For a given range [nPos, nPos + nLen[ and an index nIndex, this function
349 * basically counts the number of SwWrongArea entries starting with nIndex
350 * up to nPos + nLen. All these entries are removed.
351 *************************************************************************/
352 sal_Bool SwWrongList::Fresh( xub_StrLen &rStart, xub_StrLen &rEnd, xub_StrLen nPos,
353 xub_StrLen nLen, MSHORT nIndex, xub_StrLen nCursorPos )
355 // length of word must be greater than 0 and cursor position must be outside the word
356 sal_Bool bRet = nLen && ( nCursorPos > nPos + nLen || nCursorPos < nPos );
358 xub_StrLen nWrPos = 0;
359 xub_StrLen nWrEnd = rEnd;
360 MSHORT nCnt = nIndex;
361 if( nCnt < Count() && ( nWrPos = Pos( nIndex ) ) < nPos )
363 if( rStart > nWrPos )
364 rStart = nWrPos;
367 while( nCnt < Count() && ( nWrPos = Pos( nCnt ) ) < nPos )
368 nWrEnd = nWrPos + Len( nCnt++ );
370 if( nCnt < Count() && nWrPos == nPos && Len( nCnt ) == nLen )
372 ++nCnt;
373 bRet = sal_True;
375 else
377 if( bRet )
379 if( rStart > nPos )
380 rStart = nPos;
381 nWrEnd = nPos + nLen;
385 nPos = nPos + nLen;
387 if( nCnt < Count() && ( nWrPos = Pos( nCnt ) ) < nPos )
389 if( rStart > nWrPos )
390 rStart = nWrPos;
393 while( nCnt < Count() && ( nWrPos = Pos( nCnt ) ) < nPos )
394 nWrEnd = nWrPos + Len( nCnt++ );
396 if( rEnd < nWrEnd )
397 rEnd = nWrEnd;
399 Remove( nIndex, nCnt - nIndex );
401 return bRet;
404 void SwWrongList::Invalidate( xub_StrLen nBegin, xub_StrLen nEnd )
406 if (STRING_LEN == GetBeginInv())
407 SetInvalid( nBegin, nEnd );
408 else
409 _Invalidate( nBegin, nEnd );
412 sal_Bool SwWrongList::InvalidateWrong( )
414 if( Count() )
416 xub_StrLen nFirst = Pos( 0 );
417 xub_StrLen nLast = Pos( Count() - 1 ) + Len( Count() - 1 );
418 Invalidate( nFirst, nLast );
419 return sal_True;
421 else
422 return sal_False;
425 SwWrongList* SwWrongList::SplitList( xub_StrLen nSplitPos )
427 SwWrongList *pRet = NULL;
428 MSHORT nLst = 0;
429 xub_StrLen nWrPos;
430 xub_StrLen nWrLen;
431 while( nLst < Count() && Pos( nLst ) < nSplitPos )
432 ++nLst;
433 if( nLst && ( nWrPos = Pos( nLst - 1 ) )
434 + ( nWrLen = Len( nLst - 1 ) ) > nSplitPos )
436 nWrLen += nWrPos - nSplitPos;
437 maList[--nLst].mnPos = nSplitPos;
438 maList[nLst].mnLen = nWrLen;
440 if( nLst )
442 if( WRONGLIST_GRAMMAR == GetWrongListType() )
443 pRet = new SwGrammarMarkUp();
444 else
445 pRet = new SwWrongList( GetWrongListType() );
446 pRet->Insert(0, maList.begin(), ( nLst >= maList.size() ? maList.end() : maList.begin() + nLst ) );
447 pRet->SetInvalid( GetBeginInv(), GetEndInv() );
448 pRet->_Invalidate( nSplitPos ? nSplitPos - 1 : nSplitPos, nSplitPos );
449 Remove( 0, nLst );
451 if( STRING_LEN == GetBeginInv() )
452 SetInvalid( 0, 1 );
453 else
455 ShiftLeft( nBeginInvalid, 0, nSplitPos );
456 ShiftLeft( nEndInvalid, 0, nSplitPos );
457 _Invalidate( 0, 1 );
459 nLst = 0;
460 while( nLst < Count() )
462 nWrPos = maList[nLst].mnPos - nSplitPos;
463 maList[nLst++].mnPos = nWrPos;
465 return pRet;
468 void SwWrongList::JoinList( SwWrongList* pNext, xub_StrLen nInsertPos )
470 if (pNext)
472 DBG_ASSERT( GetWrongListType() == pNext->GetWrongListType(), "type mismatch with next list" );
474 if( pNext )
476 USHORT nCnt = Count();
477 pNext->Move( 0, nInsertPos );
478 Insert(nCnt, pNext->maList.begin(), pNext->maList.end());
480 Invalidate( pNext->GetBeginInv(), pNext->GetEndInv() );
481 if( nCnt && Count() > nCnt )
483 xub_StrLen nWrPos = Pos( nCnt );
484 xub_StrLen nWrLen = Len( nCnt );
485 if( !nWrPos )
487 nWrPos = nWrPos + nInsertPos;
488 nWrLen = nWrLen - nInsertPos;
489 maList[nCnt].mnPos = nWrPos;
490 maList[nCnt].mnLen = nWrLen;
492 if( nWrPos == Pos( nCnt - 1 ) + Len( nCnt - 1 ) )
494 nWrLen = nWrLen + Len( nCnt - 1 );
495 maList[nCnt - 1].mnLen = nWrLen;
496 Remove( nCnt, 1 );
500 Invalidate( nInsertPos ? nInsertPos - 1 : nInsertPos, nInsertPos + 1 );
504 void SwWrongList::InsertSubList( xub_StrLen nNewPos, xub_StrLen nNewLen, USHORT nWhere, SwWrongList* pSubList )
506 if (pSubList)
508 DBG_ASSERT( GetWrongListType() == pSubList->GetWrongListType(), "type mismatch with sub list" );
510 std::vector<SwWrongArea>::iterator i = maList.begin();
511 if ( nWhere >= maList.size() )
512 i = maList.end(); // robust
513 else
514 i += nWhere;
515 maList.insert(i, SwWrongArea( rtl::OUString(), 0, nNewPos, nNewLen, pSubList ) );
519 // New functions: Necessary because SwWrongList has been changed to use std::vector
520 void SwWrongList::Insert(USHORT nWhere, std::vector<SwWrongArea>::iterator startPos, std::vector<SwWrongArea>::iterator endPos)
522 std::vector<SwWrongArea>::iterator i = maList.begin();
523 if ( nWhere >= maList.size() )
524 i = maList.end(); // robust
525 else
526 i += nWhere;
527 maList.insert(i, startPos, endPos); // insert [startPos, endPos[ before i
529 // ownership of the sublist is passed to maList, therefore we have to set the
530 // pSubList-Pointers to 0
531 while ( startPos != endPos )
533 (*startPos).mpSubList = 0;
534 ++startPos;
538 void SwWrongList::Remove(USHORT nIdx, USHORT nLen )
540 if ( nIdx >= maList.size() ) return;
541 std::vector<SwWrongArea>::iterator i1 = maList.begin();
542 i1 += nIdx;
544 std::vector<SwWrongArea>::iterator i2 = i1;
545 if ( nIdx + nLen >= static_cast<USHORT>(maList.size()) )
546 i2 = maList.end(); // robust
547 else
548 i2 += nLen;
550 std::vector<SwWrongArea>::iterator iLoop = i1;
551 while ( iLoop != i2 )
553 if ( (*iLoop).mpSubList )
554 delete (*iLoop).mpSubList;
555 ++iLoop;
558 #if OSL_DEBUG_LEVEL > 1
559 const int nOldSize = Count();
560 (void) nOldSize;
561 #endif
563 maList.erase(i1, i2);
565 #if OSL_DEBUG_LEVEL > 1
566 ASSERT( Count() + nLen == nOldSize, "SwWrongList::Remove() trouble" )
567 #endif
570 void SwWrongList::RemoveEntry( xub_StrLen nBegin, xub_StrLen nEnd ) {
571 USHORT nDelPos = 0;
572 USHORT nDel = 0;
573 std::vector<SwWrongArea>::iterator aIter = maList.begin();
574 while( aIter != maList.end() && (*aIter).mnPos < nBegin )
576 ++aIter;
577 ++nDelPos;
579 if( WRONGLIST_GRAMMAR == GetWrongListType() )
581 while( aIter != maList.end() && nBegin < nEnd && nEnd > (*aIter).mnPos )
583 ++aIter;
584 ++nDel;
587 else
589 while( aIter != maList.end() && nBegin == (*aIter).mnPos && nEnd == (*aIter).mnPos +(*aIter).mnLen )
591 ++aIter;
592 ++nDel;
595 if( nDel )
596 Remove( nDelPos, nDel );
599 bool SwWrongList::LookForEntry( xub_StrLen nBegin, xub_StrLen nEnd ) {
600 std::vector<SwWrongArea>::iterator aIter = maList.begin();
601 while( aIter != maList.end() && (*aIter).mnPos < nBegin )
602 ++aIter;
603 if( aIter != maList.end() && nBegin == (*aIter).mnPos && nEnd == (*aIter).mnPos +(*aIter).mnLen )
604 return true;
605 return false;
608 void SwWrongList::Insert( const rtl::OUString& rType,
609 com::sun::star::uno::Reference< com::sun::star::container::XStringKeyMap > xPropertyBag,
610 xub_StrLen nNewPos, xub_StrLen nNewLen )
612 std::vector<SwWrongArea>::iterator aIter = maList.begin();
614 while ( aIter != maList.end() )
616 const xub_StrLen nSTPos = (*aIter).mnPos;
618 if ( nNewPos < nSTPos )
620 // insert at current position
621 break;
623 else if ( nNewPos == nSTPos )
625 while ( aIter != maList.end() && (*aIter).mnPos == nSTPos )
627 const xub_StrLen nSTLen = (*aIter).mnLen;
629 if ( nNewLen < nSTLen )
631 // insert at current position
632 break;
635 ++aIter;
638 break;
641 ++aIter;
644 maList.insert(aIter, SwWrongArea( rType, xPropertyBag, nNewPos, nNewLen, 0 ) );