File: | home/maarten/src/libreoffice/core/sw/source/core/text/wrong.cxx |
Warning: | line 895, column 48 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
52 | SwWrongList::SwWrongList( WrongListType eType ) : | |||
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 | ||||
60 | SwWrongList::~SwWrongList() | |||
61 | { | |||
62 | ClearList(); | |||
63 | } | |||
64 | ||||
65 | SwWrongList* SwWrongList::Clone() | |||
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; | |||
76 | mnBeginInvalid = rCopy.mnBeginInvalid; | |||
77 | mnEndInvalid = rCopy.mnEndInvalid; | |||
78 | for(SwWrongArea & i : maList) | |||
79 | { | |||
80 | if( i.mpSubList ) | |||
81 | i.mpSubList = i.mpSubList->Clone(); | |||
82 | } | |||
83 | } | |||
84 | ||||
85 | void SwWrongList::ClearList() | |||
86 | { | |||
87 | for (SwWrongArea & i : maList) | |||
88 | { | |||
89 | delete i.mpSubList; | |||
90 | i.mpSubList = nullptr; | |||
91 | } | |||
92 | maList.clear(); | |||
93 | } | |||
94 | ||||
95 | /** If a word is incorrectly selected, this method returns begin and length of it. | |||
96 | ||||
97 | @param[in,out] rChk starting position of the word to check | |||
98 | @param[out] rLn length of the word | |||
99 | ||||
100 | @return <true> if incorrectly selected, <false> otherwise | |||
101 | */ | |||
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 | ||||
119 | /** Calculate first incorrectly selected area. | |||
120 | ||||
121 | @param[in,out] rChk starting position of the word to check | |||
122 | @param[in,out] rLn length of the word | |||
123 | ||||
124 | @return <true> if incorrectly selected area was found, <false> otherwise | |||
125 | */ | |||
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 | ||||
157 | /** Find next incorrectly selected position. | |||
158 | ||||
159 | @param[in] rChk starting position of the word to check | |||
160 | ||||
161 | @return starting position of incorrectly selected area, <COMPLETE_STRING> otherwise | |||
162 | */ | |||
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 | ||||
183 | /** Find the first position that is greater or equal to the given value. | |||
184 | ||||
185 | @note Resulting position might be behind the last element of the array. | |||
186 | @param[in] nValue value for comparison | |||
187 | ||||
188 | @return first position that is greater or equal to the given value | |||
189 | */ | |||
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 | ||||
259 | /** Change all values after the given position. | |||
260 | ||||
261 | Needed after insert/deletion of characters. | |||
262 | ||||
263 | @param nPos position after that everything should be changed | |||
264 | @param nDiff amount how much the positions should be moved | |||
265 | */ | |||
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 ); | |||
302 | if( mnEndInvalid != COMPLETE_STRING ) | |||
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 | |||
340 | /** Remove given range of entries | |||
341 | ||||
342 | For a given range [nPos, nPos + nLen[ and an index nIndex, this function | |||
343 | basically counts the number of SwWrongArea entries starting with nIndex | |||
344 | up to nPos + nLen. All these entries are removed. | |||
345 | ||||
346 | @param rStart ??? | |||
347 | @param rEnd ??? | |||
348 | @param nPos starting position of the range | |||
349 | @param nLen length of the range | |||
350 | @param nIndex index to start lookup at | |||
351 | @param nCursorPos ??? | |||
352 | ||||
353 | @return <true> if ??? | |||
354 | */ | |||
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 | ||||
433 | bool SwWrongList::InvalidateWrong( ) | |||
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 | { | |||
464 | if( WRONGLIST_GRAMMAR == GetWrongListType() ) | |||
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 ); | |||
478 | if( mnEndInvalid != COMPLETE_STRING ) | |||
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" )do { if (true && (!(GetWrongListType() == pNext->GetWrongListType ()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/core/text/wrong.cxx" ":" "493" ": "), "%s", "type mismatch with next list"); } } while (false); | |||
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" )do { if (true && (!(GetWrongListType() == pSubList-> GetWrongListType()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/wrong.cxx" ":" "526" ": "), "%s", "type mismatch with sub list"); } } while (false); | |||
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_LEVEL1 > 0 | |||
575 | const int nOldSize = Count(); | |||
576 | #endif | |||
577 | ||||
578 | maList.erase(i1, i2); | |||
579 | ||||
580 | #if OSL_DEBUG_LEVEL1 > 0 | |||
581 | OSL_ENSURE( Count() + nLen == nOldSize, "SwWrongList::Remove() trouble" )do { if (true && (!(Count() + nLen == nOldSize))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/text/wrong.cxx" ":" "581" ": "), "%s", "SwWrongList::Remove() trouble"); } } while (false); | |||
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; | |||
590 | if( WRONGLIST_GRAMMAR == GetWrongListType() ) | |||
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 | ||||
640 | WrongListIteratorBase::WrongListIteratorBase(SwTextFrame const& rFrame, | |||
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 | ||||
652 | WrongListIteratorBase::WrongListIteratorBase(SwWrongList const& rWrongList) | |||
653 | : m_pGetWrongList(nullptr) | |||
654 | , m_pMergedPara(nullptr) | |||
655 | , m_CurrentExtent(0) | |||
656 | , m_CurrentIndex(0) | |||
657 | , m_pWrongList(&rWrongList) | |||
658 | { | |||
659 | } | |||
660 | ||||
661 | WrongListIterator::WrongListIterator(SwTextFrame const& rFrame, | |||
662 | SwWrongList const* (SwTextNode::*pGetWrongList)() const) | |||
663 | : WrongListIteratorBase(rFrame, pGetWrongList) | |||
664 | { | |||
665 | } | |||
666 | ||||
667 | WrongListIterator::WrongListIterator(SwWrongList const& rWrongList) | |||
668 | : WrongListIteratorBase(rWrongList) | |||
669 | { | |||
670 | } | |||
671 | ||||
672 | bool WrongListIterator::Check(TextFrameIndex & rStart, TextFrameIndex & rLen) | |||
673 | { | |||
674 | if (m_pMergedPara) | |||
675 | { | |||
676 | if (rStart < m_CurrentIndex) | |||
677 | { // rewind | |||
678 | m_CurrentExtent = 0; | |||
679 | m_CurrentIndex = TextFrameIndex(0); | |||
680 | } | |||
681 | while (m_CurrentExtent < m_pMergedPara->extents.size()) | |||
682 | { | |||
683 | sw::Extent const& rExtent(m_pMergedPara->extents[m_CurrentExtent]); | |||
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))(static_cast <bool> (0 < sal_Int32(rLen)) ? void (0) : __assert_fail ("0 < sal_Int32(rLen)", "/home/maarten/src/libreoffice/core/sw/source/core/text/wrong.cxx" , 691, __extension__ __PRETTY_FUNCTION__)); | |||
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)(static_cast <bool> (rLen <= nOrigLen) ? void (0) : __assert_fail ("rLen <= nOrigLen", "/home/maarten/src/libreoffice/core/sw/source/core/text/wrong.cxx" , 762, __extension__ __PRETTY_FUNCTION__)); (void) nOrigLen; | |||
763 | return true; | |||
764 | } | |||
765 | } | |||
766 | } | |||
767 | m_CurrentIndex += TextFrameIndex(rExtent.nEnd - rExtent.nStart); | |||
768 | ++m_CurrentExtent; | |||
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 | ||||
784 | const SwWrongArea* | |||
785 | WrongListIterator::GetWrongElement(TextFrameIndex const nStart) | |||
786 | { | |||
787 | if (m_pMergedPara) | |||
788 | { | |||
789 | if (nStart < m_CurrentIndex) | |||
790 | { // rewind | |||
791 | m_CurrentExtent = 0; | |||
792 | m_CurrentIndex = TextFrameIndex(0); | |||
793 | } | |||
794 | while (m_CurrentExtent < m_pMergedPara->extents.size()) | |||
795 | { | |||
796 | sw::Extent const& rExtent(m_pMergedPara->extents[m_CurrentExtent]); | |||
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); | |||
811 | ++m_CurrentExtent; | |||
812 | } | |||
813 | return nullptr; | |||
814 | } | |||
815 | else if (m_pWrongList) | |||
816 | { | |||
817 | sal_Int16 const nPos(m_pWrongList->GetWrongPos(sal_Int32(nStart))); | |||
818 | return m_pWrongList->GetElement(nPos); | |||
819 | } | |||
820 | return nullptr; | |||
821 | } | |||
822 | ||||
823 | WrongListIteratorCounter::WrongListIteratorCounter(SwTextFrame const& rFrame, | |||
824 | SwWrongList const* (SwTextNode::*pGetWrongList)() const) | |||
825 | : WrongListIteratorBase(rFrame, pGetWrongList) | |||
826 | { | |||
827 | } | |||
828 | ||||
829 | WrongListIteratorCounter::WrongListIteratorCounter(SwWrongList const& rWrongList) | |||
830 | : WrongListIteratorBase(rWrongList) | |||
831 | { | |||
832 | } | |||
833 | ||||
834 | sal_uInt16 WrongListIteratorCounter::GetElementCount() | |||
835 | { | |||
836 | if (m_pMergedPara) | |||
837 | { | |||
838 | sal_uInt16 nRet(0); | |||
839 | m_CurrentExtent = 0; | |||
840 | m_CurrentIndex = TextFrameIndex(0); | |||
841 | SwNode const* pNode(nullptr); | |||
842 | sal_uInt16 InCurrentNode(0); | |||
843 | while (m_CurrentExtent < m_pMergedPara->extents.size()) | |||
844 | { | |||
845 | sw::Extent const& rExtent(m_pMergedPara->extents[m_CurrentExtent]); | |||
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); | |||
867 | ++m_CurrentExtent; | |||
868 | } | |||
869 | return nRet; | |||
870 | } | |||
871 | else if (m_pWrongList) | |||
872 | { | |||
873 | return m_pWrongList->Count(); | |||
874 | } | |||
875 | return 0; | |||
876 | } | |||
877 | ||||
878 | std::optional<std::pair<TextFrameIndex, TextFrameIndex>> | |||
879 | WrongListIteratorCounter::GetElementAt(sal_uInt16 nIndex) | |||
880 | { | |||
881 | if (m_pMergedPara) | |||
| ||||
882 | { | |||
883 | m_CurrentExtent = 0; | |||
884 | m_CurrentIndex = TextFrameIndex(0); | |||
885 | SwNode const* pNode(nullptr); | |||
886 | sal_uInt16 InCurrentNode(0); | |||
887 | while (m_CurrentExtent < m_pMergedPara->extents.size()) | |||
888 | { | |||
889 | sw::Extent const& rExtent(m_pMergedPara->extents[m_CurrentExtent]); | |||
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>( | |||
911 | m_CurrentIndex - TextFrameIndex(rExtent.nStart - | |||
912 | std::max(rExtent.nStart, pWrong->mnPos)), | |||
913 | m_CurrentIndex - TextFrameIndex(rExtent.nStart - | |||
914 | std::min(pWrong->mnPos + pWrong->mnLen, rExtent.nEnd)))); | |||
915 | } | |||
916 | --nIndex; | |||
917 | } | |||
918 | } | |||
919 | m_CurrentIndex += TextFrameIndex(rExtent.nEnd - rExtent.nStart); | |||
920 | ++m_CurrentExtent; | |||
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: */ |