Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <vcl/wrkwin.hxx>
31 : : #include <vcl/dialog.hxx>
32 : : #include <vcl/msgbox.hxx>
33 : : #include <vcl/svapp.hxx>
34 : :
35 : : #include <impedit.hxx>
36 : : #include <editeng/editview.hxx>
37 : : #include <editeng/editeng.hxx>
38 : : #include <edtspell.hxx>
39 : : #include <editeng/flditem.hxx>
40 : : #include <editeng/fontitem.hxx>
41 : : #include <svl/intitem.hxx>
42 : : #include <svl/eitem.hxx>
43 : : #include <editeng/unolingu.hxx>
44 : : #include <linguistic/lngprops.hxx>
45 : : #include <com/sun/star/beans/XPropertySet.hpp>
46 : :
47 : : using ::rtl::OUString;
48 : : using namespace com::sun::star::uno;
49 : : using namespace com::sun::star::beans;
50 : : using namespace com::sun::star::linguistic2;
51 : :
52 : :
53 : 18 : EditSpellWrapper::EditSpellWrapper( Window* _pWin,
54 : : Reference< XSpellChecker1 > &xChecker,
55 : : sal_Bool bIsStart, sal_Bool bIsAllRight, EditView* pView ) :
56 : 18 : SvxSpellWrapper( _pWin, xChecker, bIsStart, bIsAllRight )
57 : : {
58 : : SAL_WARN_IF( !pView, "editeng", "One view has to be abandoned!" );
59 : : // Keep IgnoreList, delete ReplaceList...
60 [ - + ][ + - ]: 18 : if (SvxGetChangeAllList().is())
61 [ # # ][ # # ]: 0 : SvxGetChangeAllList()->clear();
[ # # ]
62 : 18 : pEditView = pView;
63 : 18 : }
64 : :
65 : 18 : void EditSpellWrapper::SpellStart( SvxSpellArea eArea )
66 : : {
67 : 18 : EditEngine* pEE = pEditView->GetEditEngine();
68 : 18 : ImpEditEngine* pImpEE = pEditView->GetImpEditEngine();
69 : 18 : SpellInfo* pSpellInfo = pImpEE->GetSpellInfo();
70 : :
71 [ - + ]: 18 : if ( eArea == SVX_SPELL_BODY_START )
72 : : {
73 : : // Is called when
74 : : // a) Spell-Forward has arrived at the end and should restart at the top
75 : : // IsEndDone() returns also sal_True, when backward-spelling is started at the end!
76 [ # # ]: 0 : if ( IsEndDone() )
77 : : {
78 : 0 : pSpellInfo->bSpellToEnd = sal_False;
79 : 0 : pSpellInfo->aSpellTo = pSpellInfo->aSpellStart;
80 : : pEditView->GetImpEditView()->SetEditSelection(
81 [ # # ][ # # ]: 0 : pEE->GetEditDoc().GetStartPaM() );
82 : : }
83 : : else
84 : : {
85 : 0 : pSpellInfo->bSpellToEnd = sal_True;
86 : : pSpellInfo->aSpellTo = pImpEE->CreateEPaM(
87 [ # # ]: 0 : pEE->GetEditDoc().GetStartPaM() );
88 : : }
89 : : }
90 [ + - ]: 18 : else if ( eArea == SVX_SPELL_BODY_END )
91 : : {
92 : : // Is called when
93 : : // a) Spell-Forward is launched
94 : : // IsStartDone() return also sal_True, when forward-spelling is started at the beginning!
95 [ - + ]: 18 : if ( !IsStartDone() )
96 : : {
97 : 0 : pSpellInfo->bSpellToEnd = sal_True;
98 : : pSpellInfo->aSpellTo = pImpEE->CreateEPaM(
99 [ # # ]: 0 : pEE->GetEditDoc().GetEndPaM() );
100 : : }
101 : : else
102 : : {
103 : 18 : pSpellInfo->bSpellToEnd = sal_False;
104 : 18 : pSpellInfo->aSpellTo = pSpellInfo->aSpellStart;
105 : : pEditView->GetImpEditView()->SetEditSelection(
106 [ + - ][ + - ]: 18 : pEE->GetEditDoc().GetEndPaM() );
107 : : }
108 : : }
109 : : else if ( eArea == SVX_SPELL_BODY )
110 : : {
111 : : ; // Is handled by the App through SpellNextDocument
112 : : }
113 : : else
114 : : {
115 : : OSL_FAIL( "SpellStart: Unknown Area!" );
116 : : }
117 : 18 : }
118 : :
119 : 18 : sal_Bool EditSpellWrapper::SpellContinue()
120 : : {
121 [ + - ]: 18 : SetLast( pEditView->GetImpEditEngine()->ImpSpell( pEditView ) );
122 : 18 : return GetLast().is();
123 : : }
124 : :
125 : 18 : void EditSpellWrapper::SpellEnd()
126 : : {
127 : : // Base class will show language errors...
128 : 18 : SvxSpellWrapper::SpellEnd();
129 : 18 : }
130 : :
131 : 0 : sal_Bool EditSpellWrapper::HasOtherCnt()
132 : : {
133 : 0 : return sal_False;
134 : : }
135 : :
136 : 18 : sal_Bool EditSpellWrapper::SpellMore()
137 : : {
138 : 18 : EditEngine* pEE = pEditView->GetEditEngine();
139 : 18 : ImpEditEngine* pImpEE = pEditView->GetImpEditEngine();
140 : 18 : SpellInfo* pSpellInfo = pImpEE->GetSpellInfo();
141 : 18 : sal_Bool bMore = sal_False;
142 [ - + ]: 18 : if ( pSpellInfo->bMultipleDoc )
143 : : {
144 : 0 : bMore = pEE->SpellNextDocument();
145 [ # # ]: 0 : if ( bMore )
146 : : {
147 : : // The text has been entered into the engine, when backwords then
148 : : // it must be behind the selection.
149 [ # # ]: 0 : Reference< XPropertySet > xProp( SvxGetLinguPropertySet() );
150 : : pEditView->GetImpEditView()->SetEditSelection(
151 [ # # ][ # # ]: 0 : pEE->GetEditDoc().GetStartPaM() );
[ # # ][ # # ]
152 : : }
153 : : }
154 : 18 : return bMore;
155 : : }
156 : :
157 : 0 : void EditSpellWrapper::ScrollArea()
158 : : {
159 : : // No further action needed ...
160 : : // Except for, that the area is to be scrolled in the center, and not stand
161 : : // still anywhere.
162 : 0 : }
163 : :
164 : 0 : void EditSpellWrapper::ReplaceAll( const String &rNewText,
165 : : sal_Int16 )
166 : : {
167 : : // Is called when the word is in ReplaceList of the spell checker
168 : 0 : pEditView->InsertText( rNewText );
169 : 0 : CheckSpellTo();
170 : 0 : }
171 : :
172 : 0 : void EditSpellWrapper::ChangeWord( const String& rNewWord,
173 : : const sal_uInt16 )
174 : : {
175 : : // Will be called when Word Button Change
176 : : // or internally by me ChangeAll
177 : :
178 : : // If there is a dot Punkt after the word, this dot will be stripped away.
179 : : // If '"' => PreStripped.
180 [ # # ]: 0 : String aNewWord( rNewWord );
181 [ # # ]: 0 : pEditView->InsertText( aNewWord );
182 [ # # ][ # # ]: 0 : CheckSpellTo();
183 : 0 : }
184 : :
185 : 0 : void EditSpellWrapper::ChangeThesWord( const String& rNewWord )
186 : : {
187 : 0 : pEditView->InsertText( rNewWord );
188 : 0 : CheckSpellTo();
189 : 0 : }
190 : :
191 : 0 : void EditSpellWrapper::AutoCorrect( const String&, const String& )
192 : : {
193 : 0 : }
194 : :
195 : 0 : void EditSpellWrapper::CheckSpellTo()
196 : : {
197 [ # # ]: 0 : ImpEditEngine* pImpEE = pEditView->GetImpEditEngine();
198 : 0 : SpellInfo* pSpellInfo = pImpEE->GetSpellInfo();
199 [ # # ]: 0 : EditPaM aPaM( pEditView->GetImpEditView()->GetEditSelection().Max() );
200 [ # # ]: 0 : EPaM aEPaM = pImpEE->CreateEPaM( aPaM );
201 [ # # ]: 0 : if ( aEPaM.nPara == pSpellInfo->aSpellTo.nPara )
202 : : {
203 : : // Check if SpellToEnd still has a valid Index, if replace has been
204 : : // performed in the paragraph.
205 [ # # ][ # # ]: 0 : if ( pSpellInfo->aSpellTo.nIndex > aPaM.GetNode()->Len() )
[ # # ]
206 [ # # ][ # # ]: 0 : pSpellInfo->aSpellTo.nIndex = aPaM.GetNode()->Len();
207 : : }
208 : 0 : }
209 : :
210 : : //////////////////////////////////////////////////////////////////////
211 : :
212 : : #define NOT_INVALID 0xFFFF
213 : :
214 : 37883 : WrongList::WrongList() : nInvalidStart(0), nInvalidEnd(0xFFFF) {}
215 : :
216 : 21645 : WrongList::WrongList(const WrongList& r) :
217 : : maRanges(r.maRanges),
218 : : nInvalidStart(r.nInvalidStart),
219 : 21645 : nInvalidEnd(r.nInvalidEnd) {}
220 : :
221 : 59465 : WrongList::~WrongList() {}
222 : :
223 : 23256 : bool WrongList::IsInvalid() const
224 : : {
225 : 23256 : return nInvalidStart != NOT_INVALID;
226 : : }
227 : :
228 : 2952 : void WrongList::SetValid()
229 : : {
230 : 2952 : nInvalidStart = NOT_INVALID;
231 : 2952 : nInvalidEnd = 0;
232 : 2952 : }
233 : :
234 : 1005 : void WrongList::MarkInvalid( sal_uInt16 nS, sal_uInt16 nE )
235 : : {
236 [ + + ][ - + ]: 1005 : if ( ( nInvalidStart == NOT_INVALID ) || ( nInvalidStart > nS ) )
237 : 408 : nInvalidStart = nS;
238 [ + + ]: 1005 : if ( nInvalidEnd < nE )
239 : 486 : nInvalidEnd = nE;
240 : 1005 : }
241 : :
242 : 20147 : void WrongList::TextInserted( sal_uInt16 nPos, sal_uInt16 nNew, sal_Bool bPosIsSep )
243 : : {
244 [ - + ]: 20147 : if ( !IsInvalid() )
245 : : {
246 : 0 : nInvalidStart = nPos;
247 : 0 : nInvalidEnd = nPos+nNew;
248 : : }
249 : : else
250 : : {
251 [ - + ]: 20147 : if ( nInvalidStart > nPos )
252 : 0 : nInvalidStart = nPos;
253 [ + - ]: 20147 : if ( nInvalidEnd >= nPos )
254 : 20147 : nInvalidEnd = nInvalidEnd + nNew;
255 : : else
256 : 0 : nInvalidEnd = nPos+nNew;
257 : : }
258 : :
259 [ - + ]: 20147 : for (size_t i = 0, n = maRanges.size(); i < n; ++i)
260 : : {
261 : 0 : WrongRange& rWrong = maRanges[i];
262 : 0 : bool bRefIsValid = true;
263 [ # # ]: 0 : if (rWrong.nEnd >= nPos)
264 : : {
265 : : // Move all Wrongs after the insert position...
266 [ # # ]: 0 : if (rWrong.nStart > nPos)
267 : : {
268 : 0 : rWrong.nStart += nNew;
269 : 0 : rWrong.nEnd += nNew;
270 : : }
271 : : // 1: Starts before and goes until nPos...
272 [ # # ]: 0 : else if (rWrong.nEnd == nPos)
273 : : {
274 : : // Should be halted at a blank!
275 [ # # ]: 0 : if ( !bPosIsSep )
276 : 0 : rWrong.nEnd += nNew;
277 : : }
278 : : // 2: Starts before and goes until after nPos...
279 [ # # ][ # # ]: 0 : else if ((rWrong.nStart < nPos) && (rWrong.nEnd > nPos))
280 : : {
281 : 0 : rWrong.nEnd += nNew;
282 : : // When a separator remove and re-examine the Wrong
283 [ # # ]: 0 : if ( bPosIsSep )
284 : : {
285 : : // Split Wrong...
286 : 0 : WrongRange aNewWrong(rWrong.nStart, nPos);
287 : 0 : rWrong.nStart = nPos + 1;
288 [ # # ][ # # ]: 0 : maRanges.insert(maRanges.begin() + i, aNewWrong);
289 : : // Reference no longer valid after Insert, the other
290 : : // was inserted in front of this position
291 : 0 : bRefIsValid = false;
292 : 0 : ++i; // Not this again...
293 : 0 : }
294 : : }
295 : : // 3: Attribute starts at position ..
296 [ # # ]: 0 : else if (rWrong.nStart == nPos)
297 : : {
298 : 0 : rWrong.nEnd += nNew;
299 [ # # ]: 0 : if ( bPosIsSep )
300 : 0 : ++(rWrong.nStart);
301 : : }
302 : : }
303 : : SAL_WARN_IF(bRefIsValid && rWrong.nStart >= rWrong.nEnd, "editeng",
304 : : "TextInserted, WrongRange: Start >= End?!");
305 : : (void)bRefIsValid;
306 : : }
307 : :
308 : : SAL_WARN_IF(DbgIsBuggy(), "editeng", "InsertWrong: WrongList broken!");
309 : 20147 : }
310 : :
311 : 81 : void WrongList::TextDeleted( sal_uInt16 nPos, sal_uInt16 nDeleted )
312 : : {
313 : 81 : sal_uInt16 nEndChanges = nPos+nDeleted;
314 [ - + ]: 81 : if ( !IsInvalid() )
315 : : {
316 [ # # ]: 0 : sal_uInt16 nNewInvalidStart = nPos ? nPos - 1 : 0;
317 : 0 : nInvalidStart = nNewInvalidStart;
318 : 0 : nInvalidEnd = nNewInvalidStart + 1;
319 : : }
320 : : else
321 : : {
322 [ - + ]: 81 : if ( nInvalidStart > nPos )
323 : 0 : nInvalidStart = nPos;
324 [ - + ]: 81 : if ( nInvalidEnd > nPos )
325 : : {
326 [ # # ]: 0 : if ( nInvalidEnd > nEndChanges )
327 : 0 : nInvalidEnd = nInvalidEnd - nDeleted;
328 : : else
329 : 0 : nInvalidEnd = nPos+1;
330 : : }
331 : : }
332 : :
333 [ + - ][ - + ]: 81 : for (WrongList::iterator i = begin(); i != end(); )
334 : : {
335 : 0 : sal_Bool bDelWrong = sal_False;
336 [ # # ]: 0 : if (i->nEnd >= nPos)
337 : : {
338 : : // Move all Wrongs after the insert position...
339 [ # # ]: 0 : if (i->nStart >= nEndChanges)
340 : : {
341 : 0 : i->nStart -= nDeleted;
342 : 0 : i->nEnd -= nDeleted;
343 : : }
344 : : // 1. Delete Internal Wrongs ...
345 [ # # ][ # # ]: 0 : else if (i->nStart >= nPos && i->nEnd <= nEndChanges)
[ # # ]
346 : : {
347 : 0 : bDelWrong = sal_True;
348 : : }
349 : : // 2. Wrong begins before, ends inside or behind it ...
350 [ # # ][ # # ]: 0 : else if (i->nStart <= nPos && i->nEnd > nPos)
[ # # ]
351 : : {
352 [ # # ]: 0 : if (i->nEnd <= nEndChanges) // ends inside
353 : 0 : i->nEnd = nPos;
354 : : else
355 : 0 : i->nEnd -= nDeleted; // ends after
356 : : }
357 : : // 3. Wrong begins inside, ending after ...
358 [ # # ][ # # ]: 0 : else if (i->nStart >= nPos && i->nEnd > nEndChanges)
[ # # ]
359 : : {
360 : 0 : i->nStart = nEndChanges - nDeleted;
361 : 0 : i->nEnd -= nDeleted;
362 : : }
363 : : }
364 : : SAL_WARN_IF(i->nStart >= i->nEnd, "editeng",
365 : : "TextDeleted, WrongRange: Start >= End?!");
366 [ # # ]: 0 : if ( bDelWrong )
367 : : {
368 [ # # ]: 0 : i = maRanges.erase(i);
369 : : }
370 : : else
371 : : {
372 : 0 : ++i;
373 : : }
374 : : }
375 : :
376 : : SAL_WARN_IF(DbgIsBuggy(), "editeng", "TextDeleted: WrongList broken!");
377 : 81 : }
378 : :
379 : 518 : sal_Bool WrongList::NextWrong( sal_uInt16& rnStart, sal_uInt16& rnEnd ) const
380 : : {
381 : : /*
382 : : rnStart get the start position, is possibly adjusted wrt. Wrong start
383 : : rnEnd does not have to be initialized.
384 : : */
385 [ + - ][ + + ]: 519 : for (WrongList::const_iterator i = begin(); i != end(); ++i)
386 : : {
387 [ + + ]: 518 : if ( i->nEnd > rnStart )
388 : : {
389 : 517 : rnStart = i->nStart;
390 : 517 : rnEnd = i->nEnd;
391 : 517 : return sal_True;
392 : : }
393 : : }
394 : 518 : return sal_False;
395 : : }
396 : :
397 : 197 : sal_Bool WrongList::HasWrong( sal_uInt16 nStart, sal_uInt16 nEnd ) const
398 : : {
399 [ + - ][ + + ]: 198 : for (WrongList::const_iterator i = begin(); i != end(); ++i)
400 : : {
401 [ - + ][ # # ]: 1 : if (i->nStart == nStart && i->nEnd == nEnd)
[ - + ]
402 : 0 : return sal_True;
403 [ - + ]: 1 : else if ( i->nStart >= nStart )
404 : 0 : break;
405 : : }
406 : 197 : return sal_False;
407 : : }
408 : :
409 : 2941 : sal_Bool WrongList::HasAnyWrong( sal_uInt16 nStart, sal_uInt16 nEnd ) const
410 : : {
411 [ + - ][ + + ]: 2943 : for (WrongList::const_iterator i = begin(); i != end(); ++i)
412 : : {
413 [ - + ][ # # ]: 2 : if (i->nEnd >= nStart && i->nStart < nEnd)
[ - + ]
414 : 0 : return sal_True;
415 [ - + ]: 2 : else if (i->nStart >= nEnd)
416 : 0 : break;
417 : : }
418 : 2941 : return sal_False;
419 : : }
420 : :
421 : 0 : void WrongList::ClearWrongs( sal_uInt16 nStart, sal_uInt16 nEnd,
422 : : const ContentNode* pNode )
423 : : {
424 [ # # ][ # # ]: 0 : for (WrongList::iterator i = begin(); i != end(); )
425 : : {
426 [ # # ][ # # ]: 0 : if (i->nEnd > nStart && i->nStart < nEnd)
[ # # ]
427 : : {
428 [ # # ]: 0 : if (i->nEnd > nEnd) // Runs out
429 : : {
430 : 0 : i->nStart = nEnd;
431 : : // Blanks?
432 [ # # ][ # # ]: 0 : while (i->nStart < pNode->Len() &&
[ # # ][ # # ]
[ # # ]
433 [ # # ]: 0 : (pNode->GetChar(i->nStart) == ' ' ||
434 [ # # ]: 0 : pNode->IsFeature(i->nStart)))
435 : : {
436 : 0 : ++(i->nStart);
437 : : }
438 : 0 : ++i;
439 : : }
440 : : else
441 : : {
442 [ # # ]: 0 : i = maRanges.erase(i);
443 : : // no increment here
444 : : }
445 : : }
446 : : else
447 : : {
448 : 0 : ++i;
449 : : }
450 : : }
451 : :
452 : : SAL_WARN_IF(DbgIsBuggy(), "editeng", "ClearWrongs: WrongList broken!");
453 : 0 : }
454 : :
455 : 197 : void WrongList::InsertWrong( sal_uInt16 nStart, sal_uInt16 nEnd,
456 : : sal_Bool bClearRange )
457 : : {
458 : 197 : WrongList::iterator nPos = end();
459 [ + - ][ + + ]: 198 : for (WrongList::iterator i = begin(); i != end(); ++i)
460 : : {
461 [ - + ]: 1 : if (i->nStart >= nStart )
462 : : {
463 : 0 : nPos = i;
464 [ # # ]: 0 : if ( bClearRange )
465 : : {
466 : : // It can really only happen that the Wrong starts exactly here
467 : : // and runs along, but not that there are several ranges ...
468 : : // Exactly in the range is no one allowed to be, otherwise this
469 : : // Method can not be called!
470 : : SAL_WARN_IF((i->nStart != nStart || i->nEnd <= nEnd) && i->nStart <= nEnd, "editeng", "InsertWrong: RangeMismatch!");
471 [ # # ][ # # ]: 0 : if (i->nStart == nStart && i->nEnd > nEnd)
[ # # ]
472 : 0 : i->nStart = nEnd + 1;
473 : : }
474 : 0 : break;
475 : : }
476 : : }
477 : :
478 [ + - ][ - + ]: 197 : if (nPos != maRanges.end())
479 [ # # ]: 0 : maRanges.insert(nPos, WrongRange(nStart, nEnd));
480 : : else
481 [ + - ]: 197 : maRanges.push_back(WrongRange(nStart, nEnd));
482 : :
483 : : SAL_WARN_IF(DbgIsBuggy(), "editeng", "InsertWrong: WrongList broken!");
484 : 197 : }
485 : :
486 : 0 : void WrongList::MarkWrongsInvalid()
487 : : {
488 [ # # ]: 0 : if (!maRanges.empty())
489 : 0 : MarkInvalid(maRanges.front().nStart, maRanges.back().nEnd );
490 : 0 : }
491 : :
492 : 21645 : WrongList* WrongList::Clone() const
493 : : {
494 [ + - ]: 21645 : return new WrongList(*this);
495 : : }
496 : :
497 : : // #i102062#
498 : 0 : bool WrongList::operator==(const WrongList& rCompare) const
499 : : {
500 : : // cleck direct members
501 [ # # # # : 0 : if(GetInvalidStart() != rCompare.GetInvalidStart()
# # ][ # # ]
502 : 0 : || GetInvalidEnd() != rCompare.GetInvalidEnd()
503 : 0 : || maRanges.size() != rCompare.maRanges.size())
504 : 0 : return false;
505 : :
506 : 0 : WrongList::const_iterator rCA = maRanges.begin();
507 : 0 : WrongList::const_iterator rCB = rCompare.maRanges.begin();
508 : :
509 [ # # ][ # # ]: 0 : for (; rCA != maRanges.end(); ++rCA, ++rCB)
510 : : {
511 [ # # ][ # # ]: 0 : if(rCA->nStart != rCB->nStart || rCA->nEnd != rCB->nEnd)
[ # # ]
512 : 0 : return false;
513 : : }
514 : :
515 : 0 : return true;
516 : : }
517 : :
518 : 11720 : bool WrongList::empty() const
519 : : {
520 : 11720 : return maRanges.empty();
521 : : }
522 : :
523 : 0 : void WrongList::push_back(const WrongRange& rRange)
524 : : {
525 : 0 : maRanges.push_back(rRange);
526 : 0 : }
527 : :
528 : 0 : WrongRange& WrongList::back()
529 : : {
530 : 0 : return maRanges.back();
531 : : }
532 : :
533 : 0 : const WrongRange& WrongList::back() const
534 : : {
535 : 0 : return maRanges.back();
536 : : }
537 : :
538 : 686 : WrongList::iterator WrongList::begin()
539 : : {
540 : 686 : return maRanges.begin();
541 : : }
542 : :
543 : 884 : WrongList::iterator WrongList::end()
544 : : {
545 : 884 : return maRanges.end();
546 : : }
547 : :
548 : 3656 : WrongList::const_iterator WrongList::begin() const
549 : : {
550 : 3656 : return maRanges.begin();
551 : : }
552 : :
553 : 3660 : WrongList::const_iterator WrongList::end() const
554 : : {
555 : 3660 : return maRanges.end();
556 : : }
557 : :
558 : 0 : sal_Bool WrongList::DbgIsBuggy() const
559 : : {
560 : : // Check if the ranges overlap.
561 : 0 : sal_Bool bError = sal_False;
562 [ # # ][ # # ]: 0 : for (WrongList::const_iterator i = begin(); !bError && (i != end()); ++i)
[ # # ][ # # ]
[ # # # # ]
563 : : {
564 [ # # ][ # # ]: 0 : for (WrongList::const_iterator j = i + 1; !bError && (j != end()); ++j)
[ # # ][ # # ]
[ # # ]
[ # # # # ]
565 : : {
566 : : // 1) Start before, End after the second Start
567 [ # # ][ # # ]: 0 : if (i->nStart <= j->nStart && i->nEnd >= j->nStart)
[ # # ]
568 : 0 : bError = sal_True;
569 : : // 2) Start after the second Start, but still before the second End
570 [ # # ][ # # ]: 0 : else if (i->nStart >= j->nStart && i->nStart <= j->nEnd)
[ # # ]
571 : 0 : bError = sal_True;
572 : : }
573 : : }
574 : 0 : return bError;
575 : : }
576 : :
577 : : //////////////////////////////////////////////////////////////////////
578 : :
579 : 0 : EdtAutoCorrDoc::EdtAutoCorrDoc(
580 : : EditEngine* pE, ContentNode* pN, sal_uInt16 nCrsr, sal_Unicode cIns) :
581 : : mpEditEngine(pE),
582 : : pCurNode(pN),
583 : : nCursor(nCrsr),
584 : : bAllowUndoAction(cIns != 0),
585 : 0 : bUndoAction(false) {}
586 : :
587 : 0 : EdtAutoCorrDoc::~EdtAutoCorrDoc()
588 : : {
589 [ # # ]: 0 : if ( bUndoAction )
590 [ # # ]: 0 : mpEditEngine->UndoActionEnd( EDITUNDO_INSERT );
591 [ # # ]: 0 : }
592 : :
593 : 0 : sal_Bool EdtAutoCorrDoc::Delete( sal_uInt16 nStt, sal_uInt16 nEnd )
594 : : {
595 [ # # ][ # # ]: 0 : EditSelection aSel( EditPaM( pCurNode, nStt ), EditPaM( pCurNode, nEnd ) );
[ # # ]
596 [ # # ]: 0 : mpEditEngine->DeleteSelection(aSel);
597 : : SAL_WARN_IF(nCursor < nEnd, "editeng",
598 : : "Cursor in the heart of the action?!");
599 : 0 : nCursor -= ( nEnd-nStt );
600 : 0 : bAllowUndoAction = sal_False;
601 : 0 : return sal_True;
602 : : }
603 : :
604 : 0 : sal_Bool EdtAutoCorrDoc::Insert( sal_uInt16 nPos, const String& rTxt )
605 : : {
606 [ # # ][ # # ]: 0 : EditSelection aSel = EditPaM( pCurNode, nPos );
607 [ # # ]: 0 : mpEditEngine->InsertText(aSel, rTxt);
608 : : SAL_WARN_IF(nCursor < nPos, "editeng",
609 : : "Cursor in the heart of the action?!");
610 : 0 : nCursor = nCursor + rTxt.Len();
611 : :
612 [ # # ][ # # ]: 0 : if ( bAllowUndoAction && ( rTxt.Len() == 1 ) )
[ # # ]
613 [ # # ]: 0 : ImplStartUndoAction();
614 : 0 : bAllowUndoAction = sal_False;
615 : :
616 : 0 : return sal_True;
617 : : }
618 : :
619 : 0 : sal_Bool EdtAutoCorrDoc::Replace( sal_uInt16 nPos, const String& rTxt )
620 : : {
621 : 0 : return ReplaceRange( nPos, rTxt.Len(), rTxt );
622 : : }
623 : :
624 : 0 : sal_Bool EdtAutoCorrDoc::ReplaceRange( xub_StrLen nPos, xub_StrLen nSourceLength, const String& rTxt )
625 : : {
626 : : // Actually a Replace introduce => corresponds to UNDO
627 : 0 : sal_uInt16 nEnd = nPos+nSourceLength;
628 [ # # ]: 0 : if ( nEnd > pCurNode->Len() )
629 : 0 : nEnd = pCurNode->Len();
630 : :
631 : : // #i5925# First insert new text behind to be deleted text, for keeping attributes.
632 [ # # ][ # # ]: 0 : mpEditEngine->InsertText(EditSelection(EditPaM(pCurNode, nEnd)), rTxt);
633 : : mpEditEngine->DeleteSelection(
634 [ # # ][ # # ]: 0 : EditSelection(EditPaM(pCurNode, nPos), EditPaM(pCurNode, nEnd)));
[ # # ]
635 : :
636 [ # # ]: 0 : if ( nPos == nCursor )
637 : 0 : nCursor = nCursor + rTxt.Len();
638 : :
639 [ # # ][ # # ]: 0 : if ( bAllowUndoAction && ( rTxt.Len() == 1 ) )
[ # # ]
640 : 0 : ImplStartUndoAction();
641 : :
642 : 0 : bAllowUndoAction = sal_False;
643 : :
644 : 0 : return sal_True;
645 : : }
646 : :
647 : 0 : sal_Bool EdtAutoCorrDoc::SetAttr( sal_uInt16 nStt, sal_uInt16 nEnd,
648 : : sal_uInt16 nSlotId, SfxPoolItem& rItem )
649 : : {
650 : 0 : SfxItemPool* pPool = &mpEditEngine->GetEditDoc().GetItemPool();
651 [ # # # # ]: 0 : while ( pPool->GetSecondaryPool() &&
[ # # ]
652 : 0 : !pPool->GetName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("EditEngineItemPool")) )
653 : : {
654 : 0 : pPool = pPool->GetSecondaryPool();
655 : :
656 : : }
657 : 0 : sal_uInt16 nWhich = pPool->GetWhich( nSlotId );
658 [ # # ]: 0 : if ( nWhich )
659 : : {
660 : 0 : rItem.SetWhich( nWhich );
661 : :
662 [ # # ][ # # ]: 0 : SfxItemSet aSet = mpEditEngine->GetEmptyItemSet();
663 [ # # ]: 0 : aSet.Put( rItem );
664 : :
665 [ # # ][ # # ]: 0 : EditSelection aSel( EditPaM( pCurNode, nStt ), EditPaM( pCurNode, nEnd ) );
[ # # ]
666 : 0 : aSel.Max().SetIndex( nEnd ); // ???
667 [ # # ]: 0 : mpEditEngine->SetAttribs( aSel, aSet, ATTRSPECIAL_EDGE );
668 [ # # ]: 0 : bAllowUndoAction = false;
669 : : }
670 : 0 : return sal_True;
671 : : }
672 : :
673 : 0 : sal_Bool EdtAutoCorrDoc::SetINetAttr( sal_uInt16 nStt, sal_uInt16 nEnd,
674 : : const String& rURL )
675 : : {
676 : : // Turn the Text into a command field ...
677 [ # # ][ # # ]: 0 : EditSelection aSel( EditPaM( pCurNode, nStt ), EditPaM( pCurNode, nEnd ) );
[ # # ]
678 [ # # ]: 0 : String aText = mpEditEngine->GetSelected(aSel);
679 [ # # ][ # # ]: 0 : aSel = mpEditEngine->DeleteSelection(aSel);
680 : : SAL_WARN_IF(nCursor < nEnd, "editeng",
681 : : "Cursor in the heart of the action?!");
682 : 0 : nCursor -= ( nEnd-nStt );
683 : : SvxFieldItem aField( SvxURLField( rURL, aText, SVXURLFORMAT_REPR ),
684 [ # # ][ # # ]: 0 : EE_FEATURE_FIELD );
[ # # ][ # # ]
[ # # ]
685 [ # # ]: 0 : mpEditEngine->InsertField(aSel, aField);
686 : 0 : nCursor++;
687 [ # # ]: 0 : mpEditEngine->UpdateFieldsOnly();
688 : 0 : bAllowUndoAction = false;
689 [ # # ][ # # ]: 0 : return sal_True;
690 : : }
691 : :
692 : 0 : sal_Bool EdtAutoCorrDoc::HasSymbolChars( sal_uInt16 nStt, sal_uInt16 nEnd )
693 : : {
694 [ # # ][ # # ]: 0 : sal_uInt16 nScriptType = mpEditEngine->GetScriptType( EditPaM( pCurNode, nStt ) );
[ # # ]
695 [ # # ]: 0 : sal_uInt16 nScriptFontInfoItemId = GetScriptItemId( EE_CHAR_FONTINFO, nScriptType );
696 : :
697 [ # # ]: 0 : const CharAttribList::AttribsType& rAttribs = pCurNode->GetCharAttribs().GetAttribs();
698 [ # # ][ # # ]: 0 : CharAttribList::AttribsType::const_iterator it = rAttribs.begin(), itEnd = rAttribs.end();
699 [ # # ][ # # ]: 0 : for (; it != itEnd; ++it)
[ # # ]
700 : : {
701 [ # # ]: 0 : const EditCharAttrib& rAttr = *it;
702 [ # # ]: 0 : if (rAttr.GetStart() >= nEnd)
703 : 0 : return false;
704 : :
705 [ # # # # ]: 0 : if (rAttr.Which() == nScriptFontInfoItemId &&
[ # # ]
706 : 0 : static_cast<const SvxFontItem*>(rAttr.GetItem())->GetCharSet() == RTL_TEXTENCODING_SYMBOL)
707 : : {
708 : : // check if the Attribtuteis within range...
709 [ # # ]: 0 : if (rAttr.GetEnd() >= nStt)
710 : 0 : return true;
711 : : }
712 : : }
713 : 0 : return false;
714 : : }
715 : :
716 : 0 : const String* EdtAutoCorrDoc::GetPrevPara( sal_Bool )
717 : : {
718 : : // Return previous paragraph, so that it can be determined,
719 : : // whether the current word is at the beginning of a sentence.
720 : :
721 : 0 : bAllowUndoAction = sal_False; // Not anymore ...
722 : :
723 : 0 : EditDoc& rNodes = mpEditEngine->GetEditDoc();
724 : 0 : sal_uInt16 nPos = rNodes.GetPos( pCurNode );
725 : :
726 : : // Special case: Bullet => Paragraph start => simply return NULL...
727 : : const SfxBoolItem& rBulletState = (const SfxBoolItem&)
728 : 0 : mpEditEngine->GetParaAttrib( nPos, EE_PARA_BULLETSTATE );
729 [ # # ]: 0 : sal_Bool bBullet = rBulletState.GetValue() ? sal_True : sal_False;
730 [ # # ][ # # ]: 0 : if ( !bBullet && (mpEditEngine->GetControlWord() & EE_CNTRL_OUTLINER) )
[ # # ]
731 : : {
732 : : // The Outliner has still a Bullet at Level 0.
733 : : const SfxInt16Item& rLevel = (const SfxInt16Item&)
734 : 0 : mpEditEngine->GetParaAttrib( nPos, EE_PARA_OUTLLEVEL );
735 [ # # ]: 0 : if ( rLevel.GetValue() == 0 )
736 : 0 : bBullet = sal_True;
737 : : }
738 [ # # ]: 0 : if ( bBullet )
739 : 0 : return NULL;
740 : :
741 [ # # ]: 0 : for ( sal_uInt16 n = nPos; n; )
742 : : {
743 : 0 : n--;
744 : 0 : ContentNode* pNode = rNodes[n];
745 [ # # ]: 0 : if ( pNode->Len() )
746 : 0 : return &pNode->GetString();
747 : : }
748 : 0 : return NULL;
749 : :
750 : : }
751 : :
752 : 0 : sal_Bool EdtAutoCorrDoc::ChgAutoCorrWord( sal_uInt16& rSttPos,
753 : : sal_uInt16 nEndPos, SvxAutoCorrect& rACorrect,
754 : : const String** ppPara )
755 : : {
756 : : // Paragraph-start or a blank found, search for the word
757 : : // shortcut in Auto
758 : 0 : bAllowUndoAction = sal_False; // Not anymore ...
759 : :
760 [ # # ]: 0 : String aShort( pCurNode->Copy( rSttPos, nEndPos - rSttPos ) );
761 : 0 : sal_Bool bRet = sal_False;
762 : :
763 [ # # ]: 0 : if( !aShort.Len() )
764 : 0 : return bRet;
765 : :
766 [ # # ][ # # ]: 0 : LanguageType eLang = mpEditEngine->GetLanguage( EditPaM( pCurNode, rSttPos+1 ) );
767 [ # # ][ # # ]: 0 : const SvxAutocorrWord* pFnd = rACorrect.SearchWordsInList(pCurNode->GetString(), rSttPos, nEndPos, *this, eLang);
768 [ # # ][ # # ]: 0 : if( pFnd && pFnd->IsTextOnly() )
[ # # ]
769 : : {
770 : : // then replace
771 : : EditSelection aSel( EditPaM( pCurNode, rSttPos ),
772 [ # # ][ # # ]: 0 : EditPaM( pCurNode, nEndPos ) );
[ # # ]
773 [ # # ][ # # ]: 0 : aSel = mpEditEngine->DeleteSelection(aSel);
774 : : SAL_WARN_IF(nCursor < nEndPos, "editeng",
775 : : "Cursor in the heart of the action?!");
776 : 0 : nCursor -= ( nEndPos-rSttPos );
777 [ # # ]: 0 : mpEditEngine->InsertText(aSel, pFnd->GetLong());
778 : 0 : nCursor = nCursor + pFnd->GetLong().Len();
779 [ # # ]: 0 : if( ppPara )
780 [ # # ]: 0 : *ppPara = &pCurNode->GetString();
781 : 0 : bRet = sal_True;
782 : : }
783 : :
784 [ # # ]: 0 : return bRet;
785 : : }
786 : :
787 : 0 : LanguageType EdtAutoCorrDoc::GetLanguage( sal_uInt16 nPos, sal_Bool ) const
788 : : {
789 [ # # ]: 0 : return mpEditEngine->GetLanguage( EditPaM( pCurNode, nPos+1 ) );
790 : : }
791 : :
792 : 0 : void EdtAutoCorrDoc::ImplStartUndoAction()
793 : : {
794 [ # # ][ # # ]: 0 : sal_uInt16 nPara = mpEditEngine->GetEditDoc().GetPos( pCurNode );
795 : 0 : ESelection aSel( nPara, nCursor, nPara, nCursor );
796 [ # # ]: 0 : mpEditEngine->UndoActionStart( EDITUNDO_INSERT, aSel );
797 : 0 : bUndoAction = sal_True;
798 : 0 : bAllowUndoAction = sal_False;
799 : 0 : }
800 : :
801 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|